diff --git a/forge-adventure/src/main/java/forge/adventure/Main.java b/forge-adventure/src/main/java/forge/adventure/Main.java index cf858088814..1c8a7994541 100644 --- a/forge-adventure/src/main/java/forge/adventure/Main.java +++ b/forge-adventure/src/main/java/forge/adventure/Main.java @@ -37,6 +37,7 @@ import java.nio.file.Paths; isPortraitMode = true; totalDeviceRAM = 0; GuiBase.setDeviceInfo("", "", 0, 0); + GuiBase.setIsAdventureMode(true); } diff --git a/forge-ai/src/main/java/forge/ai/AiAttackController.java b/forge-ai/src/main/java/forge/ai/AiAttackController.java index 94e600d655e..cbeeaaea18d 100644 --- a/forge-ai/src/main/java/forge/ai/AiAttackController.java +++ b/forge-ai/src/main/java/forge/ai/AiAttackController.java @@ -78,7 +78,6 @@ public class AiAttackController { private int aiAggression = 0; // added by Masher, how aggressive the ai is attack will be depending on circumstances private final boolean nextTurn; - /** *

* Constructor for ComputerUtil_Attack2. @@ -358,7 +357,7 @@ public class AiAttackController { opponentsAttackers = CardLists.filter(opponentsAttackers, new Predicate() { @Override public boolean apply(final Card c) { - return ComputerUtilCombat.canAttackNextTurn(c) && c.getNetCombatDamage() > 0; + return c.getNetCombatDamage() > 0 && ComputerUtilCombat.canAttackNextTurn(c); } }); for (final Card c : this.myList) { @@ -422,7 +421,7 @@ public class AiAttackController { int humanBasePower = ComputerUtilCombat.getAttack(this.oppList.get(0)) + humanExaltedBonus; if (finestHour) { // For Finest Hour, one creature could attack and get the bonus TWICE - humanBasePower = humanBasePower + humanExaltedBonus; + humanBasePower += humanExaltedBonus; } final int totalExaltedAttack = opp.isCardInPlay("Rafiq of the Many") ? 2 * humanBasePower : humanBasePower; @@ -470,7 +469,7 @@ public class AiAttackController { if (totalAttack > 0 && ai.getLife() <= totalAttack && !ai.cantLoseForZeroOrLessLife()) { return true; } - return ai.canReceiveCounters(CounterEnumType.POISON) && ai.getPoisonCounters() + totalPoison > 9; + return ai.getPoisonCounters() + totalPoison > 9 && ai.canReceiveCounters(CounterEnumType.POISON); } private boolean doAssault(final Player ai) { @@ -672,9 +671,9 @@ public class AiAttackController { * * @return a {@link forge.game.combat.Combat} object. */ - public final void declareAttackers(final Combat combat) { + public final int declareAttackers(final Combat combat) { if (this.attackers.isEmpty()) { - return; + return aiAggression; } // Aggro options @@ -684,14 +683,18 @@ public class AiAttackController { int extraChanceIfOppHasMana = 0; boolean tradeIfLowerLifePressure = false; boolean predictEvasion = false; + boolean simAI = false; if (ai.getController().isAI()) { AiController aic = ((PlayerControllerAi) ai.getController()).getAi(); - playAggro = aic.getBooleanProperty(AiProps.PLAY_AGGRO); - chanceToAttackToTrade = aic.getIntProperty(AiProps.CHANCE_TO_ATTACK_INTO_TRADE); - tradeIfTappedOut = aic.getBooleanProperty(AiProps.ATTACK_INTO_TRADE_WHEN_TAPPED_OUT); - extraChanceIfOppHasMana = aic.getIntProperty(AiProps.CHANCE_TO_ATKTRADE_WHEN_OPP_HAS_MANA); - tradeIfLowerLifePressure = aic.getBooleanProperty(AiProps.RANDOMLY_ATKTRADE_ONLY_ON_LOWER_LIFE_PRESSURE); - predictEvasion = aic.getBooleanProperty(AiProps.COMBAT_ATTRITION_ATTACK_EVASION_PREDICTION); + simAI = aic.usesSimulation(); + if (!simAI) { + playAggro = aic.getBooleanProperty(AiProps.PLAY_AGGRO); + chanceToAttackToTrade = aic.getIntProperty(AiProps.CHANCE_TO_ATTACK_INTO_TRADE); + tradeIfTappedOut = aic.getBooleanProperty(AiProps.ATTACK_INTO_TRADE_WHEN_TAPPED_OUT); + extraChanceIfOppHasMana = aic.getIntProperty(AiProps.CHANCE_TO_ATKTRADE_WHEN_OPP_HAS_MANA); + tradeIfLowerLifePressure = aic.getBooleanProperty(AiProps.RANDOMLY_ATKTRADE_ONLY_ON_LOWER_LIFE_PRESSURE); + predictEvasion = aic.getBooleanProperty(AiProps.COMBAT_ATTRITION_ATTACK_EVASION_PREDICTION); + } } final boolean bAssault = doAssault(ai); @@ -714,7 +717,7 @@ public class AiAttackController { if (attackMax == 0) { // can't attack anymore - return; + return aiAggression; } // Attackers that don't really have a choice @@ -751,7 +754,7 @@ public class AiAttackController { } } if (attackersLeft.isEmpty()) { - return; + return aiAggression; } } @@ -761,7 +764,7 @@ public class AiAttackController { } // Revenge of Ravens: make sure the AI doesn't kill itself and doesn't damage itself unnecessarily if (!doRevengeOfRavensAttackLogic(ai, defender, attackersLeft, numForcedAttackers, attackMax)) { - return; + return aiAggression; } if (bAssault && defender == this.defendingOpponent) { // in case we are forced to attack someone else @@ -771,14 +774,14 @@ public class AiAttackController { for (Card attacker : attackersLeft) { // reached max, breakup if (attackMax != -1 && combat.getAttackers().size() >= attackMax) - return; + return aiAggression; if (canAttackWrapper(attacker, defender) && isEffectiveAttacker(ai, attacker, combat, defender)) { combat.addAttacker(attacker, defender); } } // no more creatures to attack - return; + return aiAggression; } // Cards that are remembered to attack anyway (e.g. temporarily stolen creatures) @@ -816,7 +819,7 @@ public class AiAttackController { for (Card attacker : this.attackers) { if (canAttackWrapper(attacker, defender) && shouldAttack(ai, attacker, this.blockers, combat, defender)) { combat.addAttacker(attacker, defender); - return; + return aiAggression; } } } @@ -835,7 +838,19 @@ public class AiAttackController { } } // no more creatures to attack - return; + return aiAggression; + } + + if (simAI && ai.isCardInPlay("Reconnaissance")) { + for (Card attacker : attackersLeft) { + if (canAttackWrapper(attacker, defender)) { + // simulation will decide if attacker stays in combat based on blocks + combat.addAttacker(attacker, defender); + } + } + // safe to exert + this.aiAggression = 6; + return aiAggression; } // ******************* @@ -877,7 +892,7 @@ public class AiAttackController { for (final Card pCard : categorizedOppList) { // if the creature can attack next turn add it to counter attackers list - if (ComputerUtilCombat.canAttackNextTurn(pCard) && pCard.getNetCombatDamage() > 0) { + if (pCard.getNetCombatDamage() > 0 && ComputerUtilCombat.canAttackNextTurn(pCard)) { nextTurnAttackers.add(pCard); candidateCounterAttackDamage += pCard.getNetCombatDamage(); humanForces += 1; // player forces they might use to attack @@ -1108,6 +1123,8 @@ public class AiAttackController { defender = pwNearUlti != null ? pwNearUlti : ComputerUtilCard.getBestPlaneswalkerAI(pwDefending); } } + + return aiAggression; } /** @@ -1133,8 +1150,7 @@ public class AiAttackController { int numberOfPossibleBlockers = 0; // Is it a creature that has a more valuable ability with a tap cost than what it can do by attacking? - if ((attacker.hasSVar("NonCombatPriority")) - && (!attacker.hasKeyword(Keyword.VIGILANCE))) { + if (attacker.hasSVar("NonCombatPriority") && !attacker.hasKeyword(Keyword.VIGILANCE)) { // For each level of priority, enemy has to have life as much as the creature's power // so a priority of 4 means the creature will not attack unless it can defeat that player in 4 successful attacks. // the lower the priroity, the less willing the AI is to use the creature for attacking. @@ -1159,8 +1175,7 @@ public class AiAttackController { } boolean hasAttackEffect = attacker.getSVar("HasAttackEffect").equals("TRUE") || attacker.hasStartOfKeyword("Annihilator"); // is there a gain in attacking even when the blocker is not killed (Lifelink, Wither,...) - boolean hasCombatEffect = attacker.getSVar("HasCombatEffect").equals("TRUE") - || "Blocked".equals(attacker.getSVar("HasAttackEffect")); + boolean hasCombatEffect = attacker.getSVar("HasCombatEffect").equals("TRUE") || "Blocked".equals(attacker.getSVar("HasAttackEffect")); // contains only the defender's blockers that can actually block the attacker CardCollection validBlockers = CardLists.filter(defenders, new Predicate() { @@ -1245,7 +1260,7 @@ public class AiAttackController { canBeKilledByOne = true; isWorthLessThanAllKillers = false; hasCombatEffect = false; - } else if ((canKillAllDangerous || !canBeKilled) && ComputerUtilCard.canBeBlockedProfitably(defendingOpponent, attacker)) { + } else if ((canKillAllDangerous || !canBeKilled) && ComputerUtilCard.canBeBlockedProfitably(defendingOpponent, attacker, true)) { canKillAllDangerous = false; canBeKilled = true; } @@ -1318,7 +1333,7 @@ public class AiAttackController { return false; // don't attack } - public static List exertAttackers(List attackers) { + public static List exertAttackers(List attackers, int aggression) { List exerters = Lists.newArrayList(); for (Card c : attackers) { boolean shouldExert = false; @@ -1362,9 +1377,14 @@ public class AiAttackController { continue; } + if (!shouldExert) { + // TODO Improve when the AI wants to use Exert powers + shouldExert = aggression > 3; + } + // A specific AI condition for Exert: if specified on the card, the AI will always // exert creatures that meet this condition - if (c.hasSVar("AIExertCondition")) { + if (!shouldExert && c.hasSVar("AIExertCondition")) { if (!c.getSVar("AIExertCondition").isEmpty()) { final String needsToExert = c.getSVar("AIExertCondition"); String sVar = needsToExert.split(" ")[0]; @@ -1379,11 +1399,6 @@ public class AiAttackController { } } - if (!shouldExert && MyRandom.getRandom().nextBoolean()) { - // TODO Improve when the AI wants to use Exert powers - shouldExert = true; - } - if (shouldExert) { exerters.add(c); } diff --git a/forge-ai/src/main/java/forge/ai/AiBlockController.java b/forge-ai/src/main/java/forge/ai/AiBlockController.java index 979bf8a959d..63f7b7cbac2 100644 --- a/forge-ai/src/main/java/forge/ai/AiBlockController.java +++ b/forge-ai/src/main/java/forge/ai/AiBlockController.java @@ -73,7 +73,11 @@ public class AiBlockController { private boolean lifeInDanger = false; - public AiBlockController(Player aiPlayer) { + // set to true when AI is predicting a blocking for another player so it doesn't use hidden information + private boolean checkingOther = false; + + public AiBlockController(Player aiPlayer, boolean checkingOther) { + this.checkingOther = checkingOther; ai = aiPlayer; } @@ -295,7 +299,7 @@ public class AiBlockController { combat.addBlocker(attacker, blocker); } } - attackersLeft = (new ArrayList<>(currentAttackers)); + attackersLeft = new ArrayList<>(currentAttackers); // 6. Blockers that don't survive until the next turn anyway for (final Card attacker : attackersLeft) { @@ -322,7 +326,7 @@ public class AiBlockController { combat.addBlocker(attacker, blocker); } } - attackersLeft = (new ArrayList<>(currentAttackers)); + attackersLeft = new ArrayList<>(currentAttackers); } private Predicate rampagesOrNeedsManyToBlock(final Combat combat) { @@ -421,7 +425,7 @@ public class AiBlockController { } } - attackersLeft = (new ArrayList<>(currentAttackers)); + attackersLeft = new ArrayList<>(currentAttackers); currentAttackers = new ArrayList<>(attackersLeft); boolean considerTripleBlock = true; @@ -457,7 +461,7 @@ public class AiBlockController { return false; } final boolean randomTrade = wouldLikeToRandomlyTrade(attacker, c, combat); - return lifeInDanger || ComputerUtilCard.evaluateCreature(c) + diff < ComputerUtilCard.evaluateCreature(attacker) || randomTrade; + return lifeInDanger || randomTrade || ComputerUtilCard.evaluateCreature(c) + diff < ComputerUtilCard.evaluateCreature(attacker); } }); if (usableBlockers.size() < 2) { @@ -560,7 +564,7 @@ public class AiBlockController { } } - attackersLeft = (new ArrayList<>(currentAttackers)); + attackersLeft = new ArrayList<>(currentAttackers); } private void makeGangNonLethalBlocks(final Combat combat) { @@ -608,7 +612,7 @@ public class AiBlockController { } } - attackersLeft = (new ArrayList<>(currentAttackers)); + attackersLeft = new ArrayList<>(currentAttackers); } // Bad Trade Blocks (should only be made if life is in danger) @@ -653,7 +657,7 @@ public class AiBlockController { } } } - attackersLeft = (new ArrayList<>(currentAttackers)); + attackersLeft = new ArrayList<>(currentAttackers); } // Chump Blocks (should only be made if life is in danger) @@ -854,7 +858,7 @@ public class AiBlockController { } private void makeChumpBlocksToSavePW(Combat combat) { - if (ComputerUtilCombat.lifeInDanger(ai, combat) || ai.getLife() <= ai.getStartingLife() / 5) { + if (ai.getLife() <= ai.getStartingLife() / 5 || ComputerUtilCombat.lifeInDanger(ai, combat)) { // most likely not worth trying to protect planeswalkers when at threateningly low life or in // dangerous combat which threatens lethal or severe damage to face return; @@ -1045,7 +1049,7 @@ public class AiBlockController { makeGangBlocks(combat); // When the AI holds some Fog effect, don't bother about lifeInDanger - if (!ComputerUtil.hasAFogEffect(ai)) { + if (!ComputerUtil.hasAFogEffect(ai, checkingOther)) { lifeInDanger = ComputerUtilCombat.lifeInDanger(ai, combat); makeTradeBlocks(combat); // choose necessary trade blocks @@ -1145,7 +1149,7 @@ public class AiBlockController { // check to see if it's possible to defend a Planeswalker under attack with a chump block, // unless life is low enough to be more worried about saving preserving the life total - if (ai.getController().isAI() && !ComputerUtilCombat.lifeInDanger(ai, combat)) { + if (ai.getController().isAI()) { makeChumpBlocksToSavePW(combat); } @@ -1206,7 +1210,7 @@ public class AiBlockController { final CardCollection result = new CardCollection(); boolean newBlockerIsAdded = false; // The new blocker comes right after this one - final Card newBlockerRightAfter = (newBlockerIndex == 0 ? null : allBlockers.get(newBlockerIndex - 1)); + final Card newBlockerRightAfter = newBlockerIndex == 0 ? null : allBlockers.get(newBlockerIndex - 1); if (newBlockerRightAfter == null && damage >= ComputerUtilCombat.getEnoughDamageToKill(blocker, damage, attacker, true)) { result.add(blocker); @@ -1274,16 +1278,19 @@ public class AiBlockController { int oppCreatureCount = 0; if (ai.getController().isAI()) { AiController aic = ((PlayerControllerAi) ai.getController()).getAi(); - enableRandomTrades = aic.getBooleanProperty(AiProps.ENABLE_RANDOM_FAVORABLE_TRADES_ON_BLOCK); - randomTradeIfBehindOnBoard = aic.getBooleanProperty(AiProps.RANDOMLY_TRADE_EVEN_WHEN_HAVE_LESS_CREATS); - randomTradeIfCreatInHand = aic.getBooleanProperty(AiProps.ALSO_TRADE_WHEN_HAVE_A_REPLACEMENT_CREAT); - minRandomTradeChance = aic.getIntProperty(AiProps.MIN_CHANCE_TO_RANDOMLY_TRADE_ON_BLOCK); - maxRandomTradeChance = aic.getIntProperty(AiProps.MAX_CHANCE_TO_RANDOMLY_TRADE_ON_BLOCK); - chanceModForEmbalm = aic.getIntProperty(AiProps.CHANCE_DECREASE_TO_TRADE_VS_EMBALM); - maxCreatDiff = aic.getIntProperty(AiProps.MAX_DIFF_IN_CREATURE_COUNT_TO_TRADE); - maxCreatDiffWithRepl = aic.getIntProperty(AiProps.MAX_DIFF_IN_CREATURE_COUNT_TO_TRADE_WITH_REPL); - chanceToTradeToSaveWalker = aic.getIntProperty(AiProps.CHANCE_TO_TRADE_TO_SAVE_PLANESWALKER); - chanceToTradeDownToSaveWalker = aic.getIntProperty(AiProps.CHANCE_TO_TRADE_DOWN_TO_SAVE_PLANESWALKER); + // simulation must get same results or it may crash + if (!aic.usesSimulation()) { + enableRandomTrades = aic.getBooleanProperty(AiProps.ENABLE_RANDOM_FAVORABLE_TRADES_ON_BLOCK); + randomTradeIfBehindOnBoard = aic.getBooleanProperty(AiProps.RANDOMLY_TRADE_EVEN_WHEN_HAVE_LESS_CREATS); + randomTradeIfCreatInHand = aic.getBooleanProperty(AiProps.ALSO_TRADE_WHEN_HAVE_A_REPLACEMENT_CREAT); + minRandomTradeChance = aic.getIntProperty(AiProps.MIN_CHANCE_TO_RANDOMLY_TRADE_ON_BLOCK); + maxRandomTradeChance = aic.getIntProperty(AiProps.MAX_CHANCE_TO_RANDOMLY_TRADE_ON_BLOCK); + chanceModForEmbalm = aic.getIntProperty(AiProps.CHANCE_DECREASE_TO_TRADE_VS_EMBALM); + maxCreatDiff = aic.getIntProperty(AiProps.MAX_DIFF_IN_CREATURE_COUNT_TO_TRADE); + maxCreatDiffWithRepl = aic.getIntProperty(AiProps.MAX_DIFF_IN_CREATURE_COUNT_TO_TRADE_WITH_REPL); + chanceToTradeToSaveWalker = aic.getIntProperty(AiProps.CHANCE_TO_TRADE_TO_SAVE_PLANESWALKER); + chanceToTradeDownToSaveWalker = aic.getIntProperty(AiProps.CHANCE_TO_TRADE_DOWN_TO_SAVE_PLANESWALKER); + } } if (!enableRandomTrades) { @@ -1320,7 +1327,7 @@ public class AiBlockController { chance = Math.max(0, chance - chanceModForEmbalm); } - if (blocker.isFaceDown() && blocker.getState(CardStateName.Original).getType().isCreature()) { + if (blocker.isFaceDown() && !checkingOther && blocker.getState(CardStateName.Original).getType().isCreature()) { // if the blocker is a face-down creature (e.g. cast via Morph, Manifest), evaluate it // in relation to the original state, not to the Morph state evalBlk = ComputerUtilCard.evaluateCreature(Card.fromPaperCard(blocker.getPaperCard(), ai), false, true); @@ -1329,7 +1336,7 @@ public class AiBlockController { boolean powerParityOrHigher = blocker.getNetPower() <= attacker.getNetPower(); boolean creatureParityOrAllowedDiff = aiCreatureCount + (randomTradeIfBehindOnBoard ? maxCreatDiff : 0) >= oppCreatureCount; - boolean wantToTradeWithCreatInHand = randomTradeIfCreatInHand + boolean wantToTradeWithCreatInHand = !checkingOther && randomTradeIfCreatInHand && Iterables.any(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.CREATURES) && aiCreatureCount + maxCreatDiffWithRepl >= oppCreatureCount; boolean wantToSavePlaneswalker = MyRandom.percentTrue(chanceToSavePW) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 9777d7f9bf2..fc43bbf1bd0 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -88,6 +88,7 @@ public class AiController { private boolean cheatShuffle; private boolean useSimulation; private SpellAbilityPicker simPicker; + private int lastAttackAggression; public boolean canCheatShuffle() { return cheatShuffle; @@ -104,6 +105,10 @@ public class AiController { this.useSimulation = value; } + public int getAttackAggression() { + return lastAttackAggression; + } + public SpellAbilityPicker getSimulationPicker() { return simPicker; } @@ -294,8 +299,9 @@ public class AiController { // These checks only work if the Executing SpellAbility is an Ability_Sub. if (exSA instanceof AbilitySub && !doTrigger(exSA, false)) { // AI would not run this trigger if given the chance - if (api == null && card.isCreature() && exSA.usesTargeting() && !exSA.getTargetRestrictions().hasCandidates(exSA) && ComputerUtil.aiLifeInDanger(activatingPlayer, true, 0)) { - // trigger will not run due to lack of targets and we desperately need a creature + if (api == null && card.isCreature() && !ComputerUtilAbility.isFullyTargetable(exSA) && + (ComputerUtil.aiLifeInDanger(activatingPlayer, true, 0) || "BadETB".equals(tr.getParam("AILogic")))) { + // trigger will not run due to lack of targets and we 1. desperately need a creature or 2. are happy about that continue; } return false; @@ -651,13 +657,12 @@ public class AiController { return null; } - public boolean reserveManaSourcesForNextSpell(SpellAbility sa, SpellAbility exceptForSa) { - return reserveManaSources(sa, null, false, true, exceptForSa); - } - public boolean reserveManaSources(SpellAbility sa) { return reserveManaSources(sa, PhaseType.MAIN2, false, false, null); } + public boolean reserveManaSourcesForNextSpell(SpellAbility sa, SpellAbility exceptForSa) { + return reserveManaSources(sa, null, false, true, exceptForSa); + } public boolean reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy) { return reserveManaSources(sa, phaseType, enemy, true, null); } @@ -737,7 +742,7 @@ public class AiController { } int oldCMC = -1; - boolean xCost = sa.getPayCosts().hasXInAnyCostPart() || sa.getHostCard().hasStartOfKeyword("Strive"); + boolean xCost = sa.costHasX() || sa.getHostCard().hasStartOfKeyword("Strive"); if (!xCost) { if (!ComputerUtilCost.canPayCost(sa, player)) { // for most costs, it's OK to check if they can be paid early in order to avoid running a heavy API check @@ -751,14 +756,15 @@ public class AiController { } // state needs to be switched here so API checks evaluate the right face - if (sa.getCardState() != null && !sa.getHostCard().isInPlay() && sa.getCardState().getStateName() == CardStateName.Modal) { - sa.getHostCard().setState(CardStateName.Modal, false); + CardStateName currentState = sa.getCardState() != null && sa.getHostCard().getCurrentStateName() != sa.getCardState().getStateName() && !sa.getHostCard().isInPlay() ? sa.getHostCard().getCurrentStateName() : null; + if (currentState != null) { + sa.getHostCard().setState(sa.getCardState().getStateName(), false); } AiPlayDecision canPlay = canPlaySa(sa); // this is the "heaviest" check, which also sets up targets, defines X, etc. - if (sa.getCardState() != null && !sa.getHostCard().isInPlay() && sa.getCardState().getStateName() == CardStateName.Modal) { - sa.getHostCard().setState(CardStateName.Original, false); + if (currentState != null) { + sa.getHostCard().setState(currentState, false); } if (canPlay != AiPlayDecision.WillPlay) { @@ -900,7 +906,7 @@ public class AiController { return canPlayFromEffectAI((SpellPermanent)sa, false, true); } if (sa.usesTargeting()) { - if (!sa.isTargetNumberValid() && !sa.getTargetRestrictions().hasCandidates(sa)) { + if (!sa.isTargetNumberValid() && sa.getTargetRestrictions().getNumCandidates(sa, true) == 0) { return AiPlayDecision.TargetingFailed; } if (!StaticAbilityMustTarget.meetsMustTargetRestriction(sa)) { @@ -1436,7 +1442,7 @@ public class AiController { // declares blockers for given defender in a given combat public void declareBlockersFor(Player defender, Combat combat) { - AiBlockController block = new AiBlockController(defender); + AiBlockController block = new AiBlockController(defender, defender != player); // When player != defender, AI should declare blockers for its benefit. block.assignBlockersForCombat(combat); } @@ -1444,7 +1450,7 @@ public class AiController { public void declareAttackers(Player attacker, Combat combat) { // 12/2/10(sol) the decision making here has moved to getAttackers() AiAttackController aiAtk = new AiAttackController(attacker); - aiAtk.declareAttackers(combat); + lastAttackAggression = aiAtk.declareAttackers(combat); // if invalid: just try an attack declaration that we know to be legal if (!CombatUtil.validateAttackers(combat)) { @@ -1621,6 +1627,7 @@ public class AiController { Map params = t.getMapParams(); if ("ChangesZone".equals(params.get("Mode")) && params.containsKey("ValidCard") + && (!params.containsKey("AILogic") || !params.get("AILogic").equals("SafeToHold")) && !params.get("ValidCard").contains("nonLand") && ((params.get("ValidCard").contains("Land")) || (params.get("ValidCard").contains("Permanent"))) && "Battlefield".equals(params.get("Destination"))) { @@ -2014,8 +2021,7 @@ public class AiController { 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 + break; } } else { CardCollectionView viableOptions = CardLists.filter(pool, Predicates.and(CardPredicates.isControlledByAnyOf(sa.getActivatingPlayer().getOpponents())), @@ -2026,22 +2032,22 @@ public class AiController { } }); Card best = ComputerUtilCard.getBestAI(viableOptions); - if (best == null) { - best = Aggregates.random(pool); // should ideally never get here either + if (best != null) { + result.add(best); + break; } - result.add(best); } + result.add(Aggregates.random(pool)); // should ideally never get here break; default: CardCollection editablePool = new CardCollection(pool); for (int i = 0; i < max; i++) { Card c = player.getController().chooseSingleEntityForEffect(editablePool, sa, null, isOptional, params); - if (c != null) { - result.add(c); - editablePool.remove(c); - } else { + if (c == null) { break; } + result.add(c); + editablePool.remove(c); // Special case for Bow to My Command which simulates a complex tap cost via ChooseCard // TODO: consider enhancing support for tapXType in UnlessCost to get rid of this hack diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index 4d43e0f39d4..e59039c30cf 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -137,6 +137,9 @@ public class ComputerUtil { } if (chooseTargets != null) { chooseTargets.run(); + if (!sa.isTargetNumberValid()) { + return false; + } } final Cost cost = sa.getPayCosts(); @@ -195,7 +198,7 @@ public class ComputerUtil { // Consider the costs here for relative "scoring" if (hasDiscardHandCost(cost)) { // Null Brooch aid - restrict -= (ai.getCardsIn(ZoneType.Hand).size() * 20); + restrict -= ai.getCardsIn(ZoneType.Hand).size() * 20; } // Abilities before Spells (card advantage) @@ -234,7 +237,7 @@ public class ComputerUtil { // (Spell,Ability,Triggered) final String tgtType = sa.getParam("TargetType"); if (tgtType != null) { - restrict -= (5 * tgtType.split(",").length); + restrict -= 5 * tgtType.split(",").length; } return restrict; } @@ -1320,7 +1323,7 @@ public class ComputerUtil { } else if (sa.isPwAbility() && ai.getGame().getPhaseHandler().is(PhaseType.MAIN2)) { for (final CostPart part : abCost.getCostParts()) { if (part instanceof CostPutCounter) { - return true; + return part.convertAmount() == null || part.convertAmount() > 0 || ai.isCardInPlay("Carth the Lion"); } } } @@ -1442,11 +1445,13 @@ public class ComputerUtil { return false; } - public static boolean hasAFogEffect(final Player ai) { + public static boolean hasAFogEffect(final Player ai, boolean checkingOther) { final CardCollection all = new CardCollection(ai.getCardsIn(ZoneType.Battlefield)); all.addAll(ai.getCardsActivableInExternalZones(true)); - all.addAll(ai.getCardsIn(ZoneType.Hand)); + if (!checkingOther || ai.hasKeyword("Play with your hand revealed.")) { + all.addAll(ai.getCardsIn(ZoneType.Hand)); + } for (final Card c : all) { for (final SpellAbility sa : c.getSpellAbilities()) { @@ -1457,6 +1462,10 @@ public class ComputerUtil { // Avoid re-entry for cards already being considered (e.g. in case the AI is considering // Convoke or Improvise for a Fog-like effect) if (c.hasKeyword("Convoke") || c.hasKeyword("Improvise")) { + // TODO skipping for now else this will lead to GUI interaction + if (!c.getController().isAI()) { + continue; + } if (AiCardMemory.isRememberedCard(ai, c, AiCardMemory.MemorySet.MARKED_TO_AVOID_REENTRY)) { continue; } @@ -1483,6 +1492,7 @@ public class ComputerUtil { if (sa.getApi() != ApiType.DealDamage) { continue; } + sa.setActivatingPlayer(ai); final String numDam = sa.getParam("NumDmg"); int dmg = AbilityUtils.calculateAmount(sa.getHostCard(), numDam, sa); if (dmg <= damage) { @@ -1504,7 +1514,7 @@ public class ComputerUtil { } // Triggered abilities - if (c.isCreature() && c.isInZone(ZoneType.Battlefield) && CombatUtil.canAttack(c)) { + if (c.isCreature() && c.isInPlay() && CombatUtil.canAttack(c)) { for (final Trigger t : c.getTriggers()) { if (TriggerType.Attacks.equals(t.getMode())) { SpellAbility sa = t.ensureAbility(); @@ -1738,7 +1748,7 @@ public class ComputerUtil { if (o instanceof Card) { final Card c = (Card) o; final boolean canRemove = (c.getNetToughness() <= dmg) - || (!c.hasKeyword(Keyword.INDESTRUCTIBLE) && c.getShieldCount() == 0 && (dmg >= ComputerUtilCombat.getDamageToKill(c, false))); + || (!c.hasKeyword(Keyword.INDESTRUCTIBLE) && c.getShieldCount() == 0 && dmg >= ComputerUtilCombat.getDamageToKill(c, false)); if (!canRemove) { continue; } @@ -1760,7 +1770,7 @@ public class ComputerUtil { } if (saviourApi == ApiType.Protection) { - if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) { + if (!topStack.usesTargeting() || ProtectAi.toProtectFrom(source, saviour) == null) { continue; } } @@ -1803,7 +1813,7 @@ public class ComputerUtil { } } if (saviourApi == ApiType.Protection) { - if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) { + if (!topStack.usesTargeting() || ProtectAi.toProtectFrom(source, saviour) == null) { continue; } } @@ -1836,7 +1846,7 @@ public class ComputerUtil { continue; } if (saviourApi == ApiType.Protection) { - if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) { + if (!topStack.usesTargeting() || ProtectAi.toProtectFrom(source, saviour) == null) { continue; } } @@ -1860,11 +1870,11 @@ public class ComputerUtil { if (o instanceof Card) { final Card c = (Card) o; // give Shroud to targeted creatures - if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll && !topStack.usesTargeting()) && !grantShroud) { + if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll) && (!topStack.usesTargeting() || !grantShroud)) { continue; } if (saviourApi == ApiType.Protection) { - if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) { + if (!topStack.usesTargeting() || ProtectAi.toProtectFrom(source, saviour) == null) { continue; } } @@ -1873,7 +1883,9 @@ public class ComputerUtil { } } //Generic curse auras - else if ((threatApi == ApiType.Attach && (topStack.isCurse() || "Curse".equals(topStack.getParam("AILogic"))))) { + else if ((threatApi == ApiType.Attach && (topStack.isCurse() || "Curse".equals(topStack.getParam("AILogic")))) + && (saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll + || saviourApi == ApiType.Protection || saviourApi == null)) { AiController aic = aiPlayer.isAI() ? ((PlayerControllerAi)aiPlayer.getController()).getAi() : null; boolean enableCurseAuraRemoval = aic != null ? aic.getBooleanProperty(AiProps.ACTIVELY_DESTROY_IMMEDIATELY_UNBLOCKABLE) : false; if (enableCurseAuraRemoval) { @@ -1881,11 +1893,11 @@ public class ComputerUtil { if (o instanceof Card) { final Card c = (Card) o; // give Shroud to targeted creatures - if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll && !topStack.usesTargeting()) && !grantShroud) { + if ((saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll) && (!topStack.usesTargeting() || !grantShroud)) { continue; } if (saviourApi == ApiType.Protection) { - if (!topStack.usesTargeting() || (ProtectAi.toProtectFrom(source, saviour) == null)) { + if (!topStack.usesTargeting() || ProtectAi.toProtectFrom(source, saviour) == null) { continue; } } @@ -2045,7 +2057,7 @@ public class ComputerUtil { } // otherwise, reject bad hands or return score - if ( landSize < 2) { + if (landSize < 2) { // BAD Hands, 0 or 1 lands if (landsInDeck == 0 || library.size()/landsInDeck > 6) { // Heavy spell deck it's ok @@ -2451,7 +2463,7 @@ public class ComputerUtil { return opponent ? "Feather" : "Quill"; } // if source is not on the battlefield anymore, choose +1/+1 ones - if (!game.getCardState(source).isInZone(ZoneType.Battlefield)) { + if (!game.getCardState(source).isInPlay()) { return opponent ? "Feather" : "Quill"; } // if no hand cards, try to mill opponent @@ -2483,7 +2495,7 @@ public class ComputerUtil { } // if source is not on the battlefield anymore - if (!game.getCardState(source).isInZone(ZoneType.Battlefield)) { + if (!game.getCardState(source).isInPlay()) { return opponent ? "Strength" : "Numbers"; } @@ -2529,7 +2541,7 @@ public class ComputerUtil { } // if source is not on the battlefield anymore - if (!game.getCardState(source).isInZone(ZoneType.Battlefield)) { + if (!game.getCardState(source).isInPlay()) { return opponent ? "Sprout" : "Harvest"; } // TODO add Lifegain to +1/+1 counters trigger @@ -2958,8 +2970,8 @@ public class ComputerUtil { } }; - int numInHand = CardLists.filter(inHand, markedAsReanimator).size(); - int numInDeck = CardLists.filter(inDeck, markedAsReanimator).size(); + int numInHand = CardLists.count(inHand, markedAsReanimator); + int numInDeck = CardLists.count(inDeck, markedAsReanimator); return numInHand > 0 || numInDeck >= 3; } @@ -3028,7 +3040,7 @@ public class ComputerUtil { if (!containsAttacker) { continue; } - AiBlockController block = new AiBlockController(ai); + AiBlockController block = new AiBlockController(ai, false); block.assignBlockersForCombat(combat); // TODO predict other, noncombat sources of damage and add them to the "payment" variable. diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilAbility.java b/forge-ai/src/main/java/forge/ai/ComputerUtilAbility.java index c9aec6c625f..b590b3e23a3 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilAbility.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilAbility.java @@ -214,4 +214,15 @@ public class ComputerUtilAbility { return targeted; } + + public static boolean isFullyTargetable(SpellAbility sa) { + SpellAbility sub = sa; + while (sub != null) { + if (sub.usesTargeting() && sub.getTargetRestrictions().getNumCandidates(sub, true) < sub.getMinTargets()) { + return false; + } + sub = sub.getSubAbility(); + } + return true; + } } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 9c3ce229079..cea246c9771 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -109,7 +109,7 @@ public class ComputerUtilCard { // get biggest Artifact return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc); } - + /** * Returns the best Planeswalker from a given list * @param list list of cards to evaluate @@ -211,7 +211,7 @@ public class ComputerUtilCard { } }); } - + // get biggest Enchantment return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc); } @@ -229,7 +229,7 @@ public class ComputerUtilCard { if (land.isEmpty()) { return null; } - + // prefer to target non basic lands final List nbLand = CardLists.filter(land, Predicates.not(CardPredicates.Presets.BASIC_LANDS)); @@ -237,7 +237,7 @@ public class ComputerUtilCard { // TODO - Rank non basics? return Aggregates.random(nbLand); } - + // if no non-basic lands, target the least represented basic land type String sminBL = ""; int iminBL = Integer.MAX_VALUE; @@ -257,13 +257,14 @@ public class ComputerUtilCard { } return land.get(0); } - + final List bLand = CardLists.getType(land, sminBL); for (Card ut : Iterables.filter(bLand, CardPredicates.Presets.UNTAPPED)) { return ut; } - + + // TODO potentially risky if simulation mode currently able to reach this from triggers return Aggregates.random(bLand); // random tapped land of least represented type } @@ -348,7 +349,7 @@ public class ComputerUtilCard { if (Iterables.isEmpty(all)) { return null; } - + // get cheapest card: Card cheapest = null; @@ -357,7 +358,7 @@ public class ComputerUtilCard { cheapest = c; } } - + return cheapest; } @@ -475,12 +476,12 @@ public class ComputerUtilCard { if (Iterables.isEmpty(list)) { return null; } - + final boolean hasEnchantmants = Iterables.any(list, CardPredicates.Presets.ENCHANTMENTS); if (biasEnch && hasEnchantmants) { return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS), null, false); } - + final boolean hasArtifacts = Iterables.any(list, CardPredicates.Presets.ARTIFACTS); if (biasArt && hasArtifacts) { return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ARTIFACTS), null, false); @@ -489,17 +490,17 @@ public class ComputerUtilCard { if (biasLand && Iterables.any(list, CardPredicates.Presets.LANDS)) { return getWorstLand(CardLists.filter(list, CardPredicates.Presets.LANDS)); } - + final boolean hasCreatures = Iterables.any(list, CardPredicates.Presets.CREATURES); if (biasCreature && hasCreatures) { return getWorstCreatureAI(CardLists.filter(list, CardPredicates.Presets.CREATURES)); } - + List lands = CardLists.filter(list, CardPredicates.Presets.LANDS); if (lands.size() > 6) { return getWorstLand(lands); } - + if (hasEnchantmants || hasArtifacts) { final List ae = CardLists.filter(list, Predicates.and(Predicates.or(CardPredicates.Presets.ARTIFACTS, CardPredicates.Presets.ENCHANTMENTS), new Predicate() { @Override @@ -509,11 +510,11 @@ public class ComputerUtilCard { })); return getCheapestPermanentAI(ae, null, false); } - + if (hasCreatures) { return getWorstCreatureAI(CardLists.filter(list, CardPredicates.Presets.CREATURES)); } - + // Planeswalkers fall through to here, lands will fall through if there aren't very many return getCheapestPermanentAI(list, null, false); } @@ -644,7 +645,7 @@ public class ComputerUtilCard { } return false; } - + /** * Create a mock combat where ai is being attacked and returns the list of likely blockers. * @param ai blocking player @@ -652,7 +653,7 @@ public class ComputerUtilCard { * @return list of creatures assigned to block in the simulation */ public static CardCollectionView getLikelyBlockers(final Player ai, final CardCollectionView blockers) { - AiBlockController aiBlk = new AiBlockController(ai); + AiBlockController aiBlk = new AiBlockController(ai, false); final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); Combat combat = new Combat(opp); //Use actual attackers if available, else consider all possible attackers @@ -675,7 +676,7 @@ public class ComputerUtilCard { } return combat.getAllBlockers(); } - + /** * Decide if a creature is going to be used as a blocker. * @param ai controller of creature @@ -692,16 +693,15 @@ public class ComputerUtilCard { * @param attacker attacking creature to evaluate * @return attacker will die */ - public static boolean canBeBlockedProfitably(final Player ai, Card attacker) { - AiBlockController aiBlk = new AiBlockController(ai); + public static boolean canBeBlockedProfitably(final Player ai, Card attacker, boolean checkingOther) { + AiBlockController aiBlk = new AiBlockController(ai, checkingOther); Combat combat = new Combat(ai); combat.addAttacker(attacker, ai); - final List attackers = new ArrayList<>(); - attackers.add(attacker); + final List attackers = Lists.newArrayList(attacker); aiBlk.assignBlockersGivenAttackers(combat, attackers); return ComputerUtilCombat.attackerWouldBeDestroyed(ai, attacker, combat); } - + /** * getMostExpensivePermanentAI. * @@ -711,24 +711,24 @@ public class ComputerUtilCard { */ public static Card getMostExpensivePermanentAI(final Iterable all) { Card biggest = null; - + int bigCMC = -1; for (final Card card : all) { // TODO when PlayAi can consider MDFC this should also look at the back face (if not on stack or battlefield) int curCMC = card.getCMC(); - + // Add all cost of all auras with the same controller if (card.isEnchanted()) { final List auras = CardLists.filterControlledBy(card.getEnchantedBy(), card.getController()); curCMC += Aggregates.sum(auras, CardPredicates.Accessors.fnGetCmc) + auras.size(); } - + if (curCMC >= bigCMC) { bigCMC = curCMC; biggest = card; } } - + return biggest; } @@ -736,21 +736,21 @@ public class ComputerUtilCard { if (list.size() == 0) { return ""; } - + final Map map = Maps.newHashMap(); for (final Card c : list) { final String name = c.getName(); Integer currentCnt = map.get(name); map.put(name, currentCnt == null ? Integer.valueOf(1) : Integer.valueOf(1 + currentCnt)); - } // for - + } + int max = 0; String maxName = ""; - + for (final Entry entry : map.entrySet()) { final String type = entry.getKey(); - + if (max < entry.getValue()) { max = entry.getValue(); maxName = type; @@ -857,7 +857,7 @@ public class ComputerUtilCard { int max = 0; String maxType = ""; - + for (final Entry entry : typesInDeck.entrySet()) { final String type = entry.getKey(); @@ -866,7 +866,7 @@ public class ComputerUtilCard { maxType = type; } } - + return maxType; } @@ -918,7 +918,7 @@ public class ComputerUtilCard { return o2.getValue() - o1.getValue(); } }); - + // will this part be once dropped? List result = new ArrayList<>(cntColors); for (Pair idx : map) { // fetch color names in the same order @@ -948,7 +948,7 @@ public class ComputerUtilCard { Player opp = ai.getWeakestOpponent(); if (sa.hasParam("AILogic")) { final String logic = sa.getParam("AILogic"); - + if (logic.equals("MostProminentInHumanDeck")) { chosen.add(getMostProminentColor(CardLists.filterControlledBy(game.getCardsInGame(), opp), colorChoices)); } @@ -1047,7 +1047,7 @@ public class ComputerUtilCard { } return chosen; } - + public static boolean useRemovalNow(final SpellAbility sa, final Card c, final int dmg, ZoneType destination) { final Player ai = sa.getActivatingPlayer(); final AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); @@ -1058,16 +1058,16 @@ public class ComputerUtilCard { final int costRemoval = sa.getHostCard().getCMC(); final int costTarget = c.getCMC(); - + if (!sa.isSpell()) { return true; } - + //Check for cards that profit from spells - for example Prowess or Threshold if (phaseType == PhaseType.MAIN1 && ComputerUtil.castSpellInMain1(ai, sa)) { return true; } - + //interrupt 1: Check whether a possible blocker will be killed for the AI to make a bigger attack if (ph.is(PhaseType.MAIN1) && ph.isPlayerTurn(ai) && c.isCreature()) { AiAttackController aiAtk = new AiAttackController(ai); @@ -1107,7 +1107,7 @@ public class ComputerUtilCard { } } } - + // interrupt 3: two for one = good if (c.isEnchanted()) { boolean myEnchants = false; @@ -1121,7 +1121,7 @@ public class ComputerUtilCard { return true; //card advantage > tempo } } - + //interrupt 4: opponent pumping target (only works if the pump target is the chosen best target to begin with) final MagicStack stack = game.getStack(); if (!stack.isEmpty()) { @@ -1130,7 +1130,7 @@ public class ComputerUtilCard { return true; } } - + //burn and curse spells float valueBurn = 0; if (dmg > 0) { @@ -1146,7 +1146,7 @@ public class ComputerUtilCard { return true; } } - + //evaluate tempo gain float valueTempo = Math.max(0.1f * costTarget / costRemoval, valueBurn); if (c.isEquipped()) { @@ -1177,7 +1177,7 @@ public class ComputerUtilCard { if (valueTempo >= 0.8 && ph.getPhase().isBefore(PhaseType.COMBAT_END)) { return true; } - + //evaluate threat of targeted card float threat = 0; if (c.isCreature()) { @@ -1260,7 +1260,7 @@ public class ComputerUtilCard { if (!c.getManaAbilities().isEmpty()) { threat += 0.5f * costTarget / opp.getLandsInPlay().size(); //set back opponent's mana } - + final float valueNow = Math.max(valueTempo, threat); if (valueNow < 0.2) { //hard floor to reduce ridiculous odds for instants over time return false; @@ -1296,13 +1296,17 @@ public class ComputerUtilCard { boolean combatTrick = false; boolean holdCombatTricks = false; int chanceToHoldCombatTricks = -1; + boolean simAI = false; if (ai.getController().isAI()) { - AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); - holdCombatTricks = aic.getBooleanProperty(AiProps.TRY_TO_HOLD_COMBAT_TRICKS_UNTIL_BLOCK); - chanceToHoldCombatTricks = aic.getIntProperty(AiProps.CHANCE_TO_HOLD_COMBAT_TRICKS_UNTIL_BLOCK); + AiController aic = ((PlayerControllerAi) ai.getController()).getAi(); + simAI = aic.usesSimulation(); + if (!simAI) { + holdCombatTricks = aic.getBooleanProperty(AiProps.TRY_TO_HOLD_COMBAT_TRICKS_UNTIL_BLOCK); + chanceToHoldCombatTricks = aic.getIntProperty(AiProps.CHANCE_TO_HOLD_COMBAT_TRICKS_UNTIL_BLOCK); + } } - + if (!c.canBeTargetedBy(sa)) { return false; } @@ -1333,9 +1337,9 @@ public class ComputerUtilCard { } // buff attacker/blocker using triggered pump (unless it's lethal and we don't want to be reckless) - if (immediately && phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) && !loseCardAtEOT) { + if (immediately && phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS) && !loseCardAtEOT) { if (phase.isPlayerTurn(ai)) { - if (CombatUtil.canAttack(c)) { + if (CombatUtil.canAttack(c) || (game.getCombat() != null && c.isAttacking())) { return true; } } else { @@ -1349,7 +1353,7 @@ public class ComputerUtilCard { Card pumped = getPumpedCreature(ai, sa, c, toughness, power, keywords); List oppCreatures = opp.getCreaturesInPlay(); float chance = 0; - + //create and buff attackers if (phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) && phase.isPlayerTurn(ai) && opp.getLife() > 0) { //1. become attacker for whatever reason @@ -1385,7 +1389,7 @@ public class ComputerUtilCard { } } } - + //2. grant haste if (keywords.contains("Haste") && c.hasSickness() && !c.isTapped()) { double nonCombatChance = 0.0f; @@ -1405,7 +1409,7 @@ public class ComputerUtilCard { } chance += nonCombatChance + combatChance; } - + //3. grant evasive if (Iterables.any(oppCreatures, CardPredicates.possibleBlockers(c))) { if (!Iterables.any(oppCreatures, CardPredicates.possibleBlockers(pumped)) @@ -1414,7 +1418,7 @@ public class ComputerUtilCard { } } } - + //combat trickery if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { //clunky code because ComputerUtilCombat.combatantWouldBeDestroyed() does not work for this sort of artificial combat @@ -1444,7 +1448,7 @@ public class ComputerUtilCard { pumpedWillDie = true; } } - + //1. save combatant if (ComputerUtilCombat.combatantWouldBeDestroyed(ai, c, combat) && !pumpedWillDie && !c.hasKeyword(Keyword.INDESTRUCTIBLE)) { @@ -1452,7 +1456,7 @@ public class ComputerUtilCard { // does not check for Indestructible when computing lethal damage return true; } - + //2. kill combatant boolean survivor = false; for (Card o : opposing) { @@ -1477,7 +1481,7 @@ public class ComputerUtilCard { } } } - + //3. buff attacker if (combat.isAttacking(c) && opp.getLife() > 0) { int dmg = ComputerUtilCombat.damageIfUnblocked(c, opp, combat, true); @@ -1551,7 +1555,7 @@ public class ComputerUtilCard { } chance += value; } - + //4. lifelink if (ai.canGainLife() && ai.getLife() > 0 && !c.hasKeyword(Keyword.LIFELINK) && keywords.contains("Lifelink") && (combat.isAttacking(c) || combat.isBlocking(c))) { @@ -1560,7 +1564,7 @@ public class ComputerUtilCard { //and trample damage (if any) chance += 1.0f * dmg / ai.getLife(); } - + //5. if the life of the computer is in danger, try to pump blockers blocking Tramplers if (combat.isBlocking(c) && toughness > 0 ) { List blockedBy = combat.getAttackersBlockedBy(c); @@ -1629,7 +1633,7 @@ public class ComputerUtilCard { } } - return MyRandom.getRandom().nextFloat() < chance; + return simAI || MyRandom.getRandom().nextFloat() < chance; } /** @@ -1710,7 +1714,7 @@ public class ComputerUtilCard { applyStaticContPT(ai.getGame(), pumped, new CardCollection(c)); return pumped; } - + /** * Applies static continuous Power/Toughness effects to a (virtual) creature. * @param game game instance to work with @@ -1757,7 +1761,7 @@ public class ComputerUtilCard { } } } - + /** * Evaluate if the ability can save a target against removal * @param ai casting player @@ -1871,7 +1875,7 @@ public class ComputerUtilCard { return oppCards; } - CardCollection aiCreats = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); + CardCollection aiCreats = ai.getCreaturesInPlay(); if (temporary) { // Pump effects that add "CARDNAME can't attack" and similar things. Only do it if something is untapped. oppCards = CardLists.filter(oppCards, CardPredicates.Presets.UNTAPPED); diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index 8e55739b45c..717e0899a62 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -160,7 +160,7 @@ public class ComputerUtilCombat { list = CardLists.filter(list, new Predicate() { @Override public boolean apply(final Card c) { - return CombatUtil.canBlock(att, c) && (c.hasFirstStrike() || c.hasDoubleStrike()); + return (c.hasFirstStrike() || c.hasDoubleStrike()) && CombatUtil.canBlock(att, c); } }); @@ -324,12 +324,12 @@ public class ComputerUtilCombat { for (final Card attacker : attackers) { final List blockers = combat.getBlockers(attacker); - if ((blockers.size() == 0) + if (blockers.size() == 0 || attacker.hasKeyword("You may have CARDNAME assign its combat damage " + "as though it weren't blocked.")) { unblocked.add(attacker); } else if (attacker.hasKeyword(Keyword.TRAMPLE) - && (getAttack(attacker) > totalShieldDamage(attacker, blockers))) { + && getAttack(attacker) > totalShieldDamage(attacker, blockers)) { if (!attacker.hasKeyword(Keyword.INFECT)) { damage += getAttack(attacker) - totalShieldDamage(attacker, blockers); } @@ -366,12 +366,12 @@ public class ComputerUtilCombat { for (final Card attacker : attackers) { final List blockers = combat.getBlockers(attacker); - if ((blockers.size() == 0) + if (blockers.size() == 0 || attacker.hasKeyword("You may have CARDNAME assign its combat damage" + " as though it weren't blocked.")) { unblocked.add(attacker); } else if (attacker.hasKeyword(Keyword.TRAMPLE) - && (getAttack(attacker) > totalShieldDamage(attacker, blockers))) { + && getAttack(attacker) > totalShieldDamage(attacker, blockers)) { int trampleDamage = getAttack(attacker) - totalShieldDamage(attacker, blockers); if (attacker.hasKeyword(Keyword.INFECT)) { poison += trampleDamage; @@ -431,7 +431,7 @@ public class ComputerUtilCombat { // check for creatures that must be blocked final List attackers = combat.getAttackersOf(ai); - final List threateningCommanders = getLifeThreateningCommanders(ai,combat); + final List threateningCommanders = getLifeThreateningCommanders(ai, combat); for (final Card attacker : attackers) { final List blockers = combat.getBlockers(attacker); @@ -457,8 +457,12 @@ public class ComputerUtilCombat { } } - int threshold = (((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.AI_IN_DANGER_THRESHOLD)); - int maxTreshold = (((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.AI_IN_DANGER_MAX_THRESHOLD)) - threshold; + int threshold = 0; + int maxTreshold = 0; + if (ai.getController().isAI()) { + threshold = ((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.AI_IN_DANGER_THRESHOLD); + maxTreshold = ((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.AI_IN_DANGER_MAX_THRESHOLD) - threshold; + } int chance = MyRandom.getRandom().nextInt(80) + 5; while (maxTreshold > 0) { @@ -617,7 +621,7 @@ public class ComputerUtilCombat { if (flankingMagnitude >= defender.getNetToughness()) { return 0; } - if (flankingMagnitude >= (defender.getNetToughness() - defender.getDamage()) + if (flankingMagnitude >= defender.getNetToughness() - defender.getDamage() && !defender.hasKeyword(Keyword.INDESTRUCTIBLE)) { return 0; } @@ -1660,7 +1664,7 @@ public class ComputerUtilCombat { */ public static boolean combatantCantBeDestroyed(Player ai, final Card combatant) { // either indestructible or may regenerate - if (combatant.hasKeyword(Keyword.INDESTRUCTIBLE) || (ComputerUtil.canRegenerate(ai, combatant))) { + if (combatant.hasKeyword(Keyword.INDESTRUCTIBLE) || ComputerUtil.canRegenerate(ai, combatant)) { return true; } @@ -1715,7 +1719,7 @@ public class ComputerUtilCombat { if (flankingMagnitude >= blocker.getNetToughness()) { return false; } - if ((flankingMagnitude >= (blocker.getNetToughness() - blocker.getDamage())) + if (flankingMagnitude >= blocker.getNetToughness() - blocker.getDamage() && !blocker.hasKeyword(Keyword.INDESTRUCTIBLE)) { return false; } @@ -2510,10 +2514,10 @@ public class ComputerUtilCombat { } // 2. Otherwise, go through the list of options one by one, choose the first one that can't be blocked profitably. for (GameEntity p : defenders) { - if (p instanceof Player && !ComputerUtilCard.canBeBlockedProfitably((Player)p, attacker)) { + if (p instanceof Player && !ComputerUtilCard.canBeBlockedProfitably((Player)p, attacker, true)) { return p; } - if (p instanceof Card && !ComputerUtilCard.canBeBlockedProfitably(((Card)p).getController(), attacker)) { + if (p instanceof Card && !ComputerUtilCard.canBeBlockedProfitably(((Card)p).getController(), attacker, true)) { return p; } } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java index cce3219276d..fdc52790d6f 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java @@ -139,7 +139,7 @@ public class ComputerUtilCost { if (source.getAbilityText().contains("Bloodrush")) { continue; } else if (ai.getGame().getPhaseHandler().is(PhaseType.END_OF_TURN, ai) - && ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize()) { + && !ai.isUnlimitedHandSize() && ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize()) { // Better do something than just discard stuff return true; } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java index 66b2150eeac..292aa19adf1 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java @@ -299,6 +299,14 @@ public class ComputerUtilMana { }); saList = filteredList; break; + case "NotSameCard": + saList = Lists.newArrayList(Iterables.filter(filteredList, new Predicate() { + @Override + public boolean apply(final SpellAbility saPay) { + return !saPay.getHostCard().getName().equals(sa.getHostCard().getName()); + } + })); + break; default: break; } @@ -363,7 +371,7 @@ public class ComputerUtilMana { // Exception: when paying generic mana with Cavern of Souls, prefer the colored mana producing ability // to attempt to make the spell uncounterable when possible. if (ComputerUtilAbility.getAbilitySourceName(ma).equals("Cavern of Souls") - && saHost.getType().getCreatureTypes().contains(ma.getHostCard().getChosenType())) { + && saHost.getType().hasCreatureType(ma.getHostCard().getChosenType())) { if (toPay == ManaCostShard.COLORLESS && cost.getUnpaidShards().contains(ManaCostShard.GENERIC)) { // Deprioritize Cavern of Souls, try to pay generic mana with it instead to use the NoCounter ability continue; @@ -1229,15 +1237,14 @@ public class ComputerUtilMana { return false; } - AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); - int chanceToReserve = aic.getIntProperty(AiProps.RESERVE_MANA_FOR_MAIN2_CHANCE); - // Mana reserved for spell synchronization if (AiCardMemory.isRememberedCard(ai, sourceCard, AiCardMemory.MemorySet.HELD_MANA_SOURCES_FOR_NEXT_SPELL)) { return true; } PhaseType curPhase = ai.getGame().getPhaseHandler().getPhase(); + AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); + int chanceToReserve = aic.getIntProperty(AiProps.RESERVE_MANA_FOR_MAIN2_CHANCE); // For combat tricks, always obey mana reservation if (curPhase == PhaseType.COMBAT_DECLARE_BLOCKERS || curPhase == PhaseType.CLEANUP) { diff --git a/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java b/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java index 1ba7c81e222..0bd597ae759 100644 --- a/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java +++ b/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java @@ -33,7 +33,7 @@ public class CreatureEvaluator implements Function { } int power = getEffectivePower(c); final int toughness = getEffectiveToughness(c); - + // TODO replace with ReplacementEffect checks if (c.hasKeyword("Prevent all combat damage that would be dealt by CARDNAME.") || c.hasKeyword("Prevent all damage that would be dealt by CARDNAME.") @@ -49,7 +49,7 @@ public class CreatureEvaluator implements Function { if (considerCMC) { value += addValue(c.getCMC() * 5, "cmc"); } - + // Evasion keywords if (c.hasKeyword(Keyword.FLYING)) { value += addValue(power * 10, "flying"); @@ -76,7 +76,7 @@ public class CreatureEvaluator implements Function { value += addValue(power * 3, "block-restrict"); } } - + // Other good keywords if (power > 0) { if (c.hasKeyword(Keyword.DOUBLE_STRIKE)) { @@ -105,7 +105,7 @@ public class CreatureEvaluator implements Function { value += addValue(c.getKeywordMagnitude(Keyword.RAMPAGE), "rampage"); value += addValue(c.getKeywordMagnitude(Keyword.AFFLICT) * 5, "afflict"); } - + value += addValue(c.getKeywordMagnitude(Keyword.BUSHIDO) * 16, "bushido"); value += addValue(c.getAmountOfKeyword(Keyword.FLANKING) * 15, "flanking"); value += addValue(c.getAmountOfKeyword(Keyword.EXALTED) * 15, "exalted"); @@ -127,7 +127,7 @@ public class CreatureEvaluator implements Function { if (c.hasKeyword("CARDNAME can block creatures with shadow as though they didn't have shadow.")) { value += addValue(3, "shadow-block"); } - + // Protection if (c.hasKeyword(Keyword.INDESTRUCTIBLE)) { value += addValue(70, "darksteel"); @@ -161,11 +161,11 @@ public class CreatureEvaluator implements Function { }/* else if (c.hasKeyword("CARDNAME can block only creatures with flying.")) { value -= subValue(toughness * 5, "reverse-reach"); }//*/ - + if (c.hasSVar("DestroyWhenDamaged")) { value -= subValue((toughness - 1) * 9, "dies-to-dmg"); } - + if (c.hasKeyword("CARDNAME can't attack or block.")) { value = addValue(50 + (c.getCMC() * 5), "useless"); // reset everything - useless } @@ -185,7 +185,7 @@ public class CreatureEvaluator implements Function { } else if (c.hasKeyword(Keyword.ECHO) && c.cameUnderControlSinceLastUpkeep()) { value -= subValue(10, "echo-unpaid"); } - + if (c.hasStartOfKeyword("At the beginning of your upkeep, CARDNAME deals")) { value -= subValue(20, "upkeep-dmg"); } @@ -198,7 +198,7 @@ public class CreatureEvaluator implements Function { if (c.getSVar("Targeting").equals("Dies")) { value -= subValue(25, "dies"); } - + for (final SpellAbility sa : c.getSpellAbilities()) { if (sa.isAbility()) { value += addValue(evaluateSpellAbility(sa), "sa: " + sa); @@ -207,11 +207,11 @@ public class CreatureEvaluator implements Function { if (!c.getManaAbilities().isEmpty()) { value += addValue(10, "manadork"); } - + if (c.isUntapped()) { value += addValue(1, "untapped"); } - + // paired creatures are more valuable because they grant a bonus to the other creature if (c.isPaired()) { value += addValue(14, "paired"); diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index fee43f50e54..c94ce865d80 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -330,7 +330,7 @@ public class PlayerControllerAi extends PlayerController { @Override public List exertAttackers(List attackers) { - return AiAttackController.exertAttackers(attackers); + return AiAttackController.exertAttackers(attackers, brains.getAttackAggression()); } @Override @@ -797,7 +797,7 @@ public class PlayerControllerAi extends PlayerController { return true; } else { Card rem = (Card) source.getFirstRemembered(); - if (!rem.isInZone(ZoneType.Battlefield)) { + if (!rem.isInPlay()) { return true; } } @@ -806,7 +806,7 @@ public class PlayerControllerAi extends PlayerController { if (source.getRememberedCount() > 0) { Card rem = (Card) source.getFirstRemembered(); // avoid pumping opponent creature - if (!rem.isInZone(ZoneType.Battlefield) || rem.getController().isOpponentOf(source.getController())) { + if (!rem.isInPlay() || rem.getController().isOpponentOf(source.getController())) { return true; } for (Card c : source.getController().getCreaturesInPlay()) { diff --git a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java index a49de701014..400db29d152 100644 --- a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java @@ -73,7 +73,7 @@ public abstract class SpellAbilityAi { if (sa.hasParam("AILogic")) { final String logic = sa.getParam("AILogic"); final boolean alwaysOnDiscard = "AlwaysOnDiscard".equals(logic) && ai.getGame().getPhaseHandler().is(PhaseType.END_OF_TURN, ai) - && ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize(); + && !ai.isUnlimitedHandSize() && ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize(); if (!checkAiLogic(ai, sa, logic)) { return false; } @@ -162,21 +162,21 @@ public abstract class SpellAbilityAi { */ protected boolean checkApiLogic(final Player ai, final SpellAbility sa) { if (ComputerUtil.preventRunAwayActivations(sa)) { - return false; // prevent infinite loop + return false; // prevent infinite loop } return MyRandom.getRandom().nextFloat() < .8f; // random success } public final boolean doTriggerAI(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) { + // this evaluation order is currently intentional as it does more stuff that helps avoiding some crashes if (!ComputerUtilCost.canPayCost(sa, aiPlayer) && !mandatory) { return false; } // a mandatory SpellAbility with targeting but without candidates, // does not need to go any deeper - if (sa.usesTargeting() && mandatory && !sa.isTargetNumberValid() - && !sa.getTargetRestrictions().hasCandidates(sa)) { - return false; + if (sa.usesTargeting() && mandatory && sa.getTargetRestrictions().getNumCandidates(sa, true) == 0) { + return sa.isTargetNumberValid(); } return doTriggerNoCostWithSubs(aiPlayer, sa, mandatory); diff --git a/forge-ai/src/main/java/forge/ai/ability/AddTurnAi.java b/forge-ai/src/main/java/forge/ai/ability/AddTurnAi.java index f8d1c1c9891..e67ddaee73e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/AddTurnAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/AddTurnAi.java @@ -24,6 +24,8 @@ import org.apache.commons.lang3.StringUtils; import forge.ai.SpellAbilityAi; import forge.game.ability.AbilityUtils; import forge.game.player.Player; +import forge.game.player.PlayerCollection; +import forge.game.player.PlayerPredicates; import forge.game.spellability.SpellAbility; /** @@ -38,7 +40,8 @@ public class AddTurnAi extends SpellAbilityAi { @Override protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { - final Player opp = ai.getWeakestOpponent(); + PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + Player opp = targetableOpps.min(PlayerPredicates.compareByLife()); if (sa.usesTargeting()) { sa.resetTargets(); @@ -51,7 +54,7 @@ public class AddTurnAi extends SpellAbilityAi { break; } } - if (!sa.getTargetRestrictions().isMinTargetsChosen(sa.getHostCard(), sa) && sa.canTarget(opp)) { + if (!sa.getTargetRestrictions().isMinTargetsChosen(sa.getHostCard(), sa) && opp != null) { sa.getTargets().add(opp); } else { return false; diff --git a/forge-ai/src/main/java/forge/ai/ability/AttachAi.java b/forge-ai/src/main/java/forge/ai/ability/AttachAi.java index e08152d3abd..363115939f3 100644 --- a/forge-ai/src/main/java/forge/ai/ability/AttachAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/AttachAi.java @@ -233,7 +233,7 @@ public class AttachAi extends SpellAbilityAi { boolean hasFloatMana = ai.getManaPool().totalMana() > 0; boolean willDiscardNow = game.getPhaseHandler().is(PhaseType.END_OF_TURN, ai) - && ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize(); + && !ai.isUnlimitedHandSize() && ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize(); boolean willDieNow = combat != null && ComputerUtilCombat.lifeInSeriousDanger(ai, combat); boolean willRespondToStack = canRespondToStack && MyRandom.percentTrue(chanceToRespondToStack); boolean willCastEarly = MyRandom.percentTrue(chanceToCastEarly); @@ -916,7 +916,7 @@ public class AttachAi extends SpellAbilityAi { prefList = CardLists.filter(prefList, new Predicate() { @Override public boolean apply(final Card c) { - return ComputerUtilCombat.canAttackNextTurn(c) && c.getNetPower() > 0; + return c.getNetPower() > 0 && ComputerUtilCombat.canAttackNextTurn(c); } }); } @@ -1278,7 +1278,7 @@ public class AttachAi extends SpellAbilityAi { if (!c.isCreature()) { return true; } - return ComputerUtilCombat.canAttackNextTurn(c) && powerBonus + c.getNetPower() > 0; + return powerBonus + c.getNetPower() > 0 && ComputerUtilCombat.canAttackNextTurn(c); } }); } @@ -1588,8 +1588,8 @@ public class AttachAi extends SpellAbilityAi { if (evasive) { return card.getNetCombatDamage() + powerBonus > 0 - && ComputerUtilCombat.canAttackNextTurn(card) - && canBeBlocked; + && canBeBlocked + && ComputerUtilCombat.canAttackNextTurn(card); } else if (keyword.equals("Haste")) { return card.hasSickness() && ph.isPlayerTurn(sa.getActivatingPlayer()) && !card.isTapped() && card.getNetCombatDamage() + powerBonus > 0 @@ -1609,8 +1609,8 @@ public class AttachAi extends SpellAbilityAi { && (ComputerUtilCombat.canAttackNextTurn(card) || CombatUtil.canBlock(card, true)); } else if (keyword.startsWith("Flanking")) { return card.getNetCombatDamage() + powerBonus > 0 - && ComputerUtilCombat.canAttackNextTurn(card) - && canBeBlocked; + && canBeBlocked + && ComputerUtilCombat.canAttackNextTurn(card); } else if (keyword.startsWith("Bushido")) { return (canBeBlocked && ComputerUtilCombat.canAttackNextTurn(card)) || CombatUtil.canBlock(card, true); @@ -1652,9 +1652,9 @@ public class AttachAi extends SpellAbilityAi { if (keyword.endsWith("CARDNAME can't attack.") || keyword.equals("Defender") || keyword.endsWith("CARDNAME can't attack or block.")) { - return ComputerUtilCombat.canAttackNextTurn(card) && card.getNetCombatDamage() >= 1; + return card.getNetCombatDamage() >= 1 && ComputerUtilCombat.canAttackNextTurn(card); } else if (keyword.endsWith("CARDNAME attacks each turn if able.") || keyword.endsWith("CARDNAME attacks each combat if able.")) { - return ComputerUtilCombat.canAttackNextTurn(card) && CombatUtil.canBlock(card, true) && !ai.getCreaturesInPlay().isEmpty(); + return !ai.getCreaturesInPlay().isEmpty() && ComputerUtilCombat.canAttackNextTurn(card) && CombatUtil.canBlock(card, true); } else if (keyword.endsWith("CARDNAME can't block.")) { return CombatUtil.canBlock(card, true); } else if (keyword.endsWith("CARDNAME's activated abilities can't be activated.")) { @@ -1665,10 +1665,10 @@ public class AttachAi extends SpellAbilityAi { } return false; } else if (keyword.endsWith("Prevent all combat damage that would be dealt by CARDNAME.")) { - return ComputerUtilCombat.canAttackNextTurn(card) && card.getNetCombatDamage() >= 1; + return card.getNetCombatDamage() >= 1 && ComputerUtilCombat.canAttackNextTurn(card); } else if (keyword.endsWith("Prevent all combat damage that would be dealt to and dealt by CARDNAME.") || keyword.endsWith("Prevent all damage that would be dealt to and dealt by CARDNAME.")) { - return ComputerUtilCombat.canAttackNextTurn(card) && card.getNetCombatDamage() >= 2; + return card.getNetCombatDamage() >= 2 && ComputerUtilCombat.canAttackNextTurn(card); } else if (keyword.endsWith("CARDNAME doesn't untap during your untap step.")) { return !card.isUntapped(); } diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java index 2b621d1003a..9530308fe7f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java @@ -1699,19 +1699,21 @@ public class ChangeZoneAi extends SpellAbilityAi { if (card.isToken()) { return false; } - if (card.isCreature() && ComputerUtilCard.isUselessCreature(decider, card)) { return true; - } else if (card.isEquipped()) { + } + if (card.isEquipped()) { return false; - } else if (card.isEnchanted()) { + } + if (card.isEnchanted()) { for (Card enc : card.getEnchantedBy()) { if (enc.getOwner().isOpponentOf(decider)) { return true; } } return false; - } else if (card.hasCounters()) { + } + if (card.hasCounters()) { if (card.isPlaneswalker()) { int maxLoyaltyToConsider = 2; int loyaltyDiff = 2; diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java index f6680775cab..1755541f5ea 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAllAi.java @@ -392,15 +392,19 @@ public class ChangeZoneAllAi extends SpellAbilityAi { PlayerPredicates.isTargetableBy(sa))); if (oppList.isEmpty()) { + if (mandatory && !sa.isTargetNumberValid() && sa.canTarget(ai)) { + sa.resetTargets(); + sa.getTargets().add(ai); + return true; + } return false; } // get the one with the most handsize - Player oppTarget = Collections.max(oppList, - PlayerPredicates.compareByZoneSize(origin)); + Player oppTarget = Collections.max(oppList, PlayerPredicates.compareByZoneSize(origin)); // set the target - if (!oppTarget.getCardsIn(ZoneType.Hand).isEmpty()) { + if (!oppTarget.getCardsIn(ZoneType.Hand).isEmpty() || mandatory) { sa.resetTargets(); sa.getTargets().add(oppTarget); } else { @@ -434,7 +438,12 @@ public class ChangeZoneAllAi extends SpellAbilityAi { PlayerPredicates.isTargetableBy(sa))); if (oppList.isEmpty()) { - return false; + if (mandatory && !sa.isTargetNumberValid() && sa.canTarget(ai)) { + sa.resetTargets(); + sa.getTargets().add(ai); + return true; + } + return sa.isTargetNumberValid(); } // get the one with the most in graveyard @@ -443,7 +452,7 @@ public class ChangeZoneAllAi extends SpellAbilityAi { AiPlayerPredicates.compareByZoneValue(sa.getParam("ChangeType"), origin, sa)); // set the target - if (!oppTarget.getCardsIn(ZoneType.Graveyard).isEmpty()) { + if (!oppTarget.getCardsIn(ZoneType.Graveyard).isEmpty() || mandatory) { sa.resetTargets(); sa.getTargets().add(oppTarget); } else { diff --git a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java index 36fee21c07d..f0cf10e2205 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java @@ -69,6 +69,9 @@ public class CharmAi extends SpellAbilityAi { if (timingRight) { // Set minimum choices for triggers where chooseMultipleOptionsAi() returns null chosenList = chooseOptionsAi(choices, ai, true, num, min, sa.hasParam("CanRepeatModes")); + if (chosenList.isEmpty() && min != 0) { + return false; + } } else { return false; } @@ -251,4 +254,23 @@ public class CharmAi extends SpellAbilityAi { public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable opponents, Map params) { return Aggregates.random(opponents); } + + @Override + protected boolean doTriggerAINoCost(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) { + // already done by chooseOrderOfSimultaneousStackEntry + if (sa.getChosenList() != null) { + return true; + } + return super.doTriggerAINoCost(aiPlayer, sa, mandatory); + } + + @Override + public boolean chkDrawbackWithSubs(Player aiPlayer, AbilitySub ab) { + // choices were already targeted + if (ab.getRootAbility().getChosenList() != null) { + return true; + } + return super.chkDrawbackWithSubs(aiPlayer, ab); + } + } diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java index 2a6e465865a..31746c3e52c 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java @@ -4,7 +4,6 @@ import forge.ai.AiAttackController; import forge.ai.SpellAbilityAi; import forge.game.player.Player; import forge.game.spellability.SpellAbility; -import forge.game.spellability.TargetRestrictions; import forge.util.MyRandom; public class ChooseEvenOddAi extends SpellAbilityAi { @@ -14,8 +13,7 @@ public class ChooseEvenOddAi extends SpellAbilityAi { if (!sa.hasParam("AILogic")) { return false; } - TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { sa.resetTargets(); Player opp = AiAttackController.choosePreferredDefenderPlayer(aiPlayer); if (sa.canTarget(opp)) { @@ -34,4 +32,3 @@ public class ChooseEvenOddAi extends SpellAbilityAi { } } - diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java index 433b1af574f..7f181a24776 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java @@ -295,7 +295,7 @@ public class ChooseGenericEffectAi extends SpellAbilityAi { // if host would put into the battlefield attacking if (combat != null && combat.isAttacking(host)) { final Player defender = combat.getDefenderPlayerByAttacker(host); - if (defender.canLoseLife() && !ComputerUtilCard.canBeBlockedProfitably(defender, copy)) { + if (defender.canLoseLife() && !ComputerUtilCard.canBeBlockedProfitably(defender, copy, true)) { return counterSA; } return tokenSA; @@ -306,7 +306,7 @@ public class ChooseGenericEffectAi extends SpellAbilityAi { for (final Player opp : player.getOpponents()) { if (CombatUtil.canAttack(copy, opp) && opp.canLoseLife() && - !ComputerUtilCard.canBeBlockedProfitably(opp, copy)) + !ComputerUtilCard.canBeBlockedProfitably(opp, copy, true)) return counterSA; } } diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java index 06d132f5347..99b10c6e5ff 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java @@ -6,7 +6,6 @@ import forge.ai.SpellAbilityAi; import forge.game.ability.AbilityUtils; import forge.game.player.Player; import forge.game.spellability.SpellAbility; -import forge.game.spellability.TargetRestrictions; import forge.util.MyRandom; public class ChooseNumberAi extends SpellAbilityAi { @@ -44,8 +43,7 @@ public class ChooseNumberAi extends SpellAbilityAi { return ownCreatureCount > oppMaxCreatureCount + 2 || ownCreatureCount < Math.min(oppMaxCreatureCount, maxChoiceLimit); } - TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { sa.resetTargets(); Player opp = AiAttackController.choosePreferredDefenderPlayer(aiPlayer); if (sa.canTarget(opp)) { diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseSourceAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseSourceAi.java index 7e2805a9add..78848367229 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseSourceAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseSourceAi.java @@ -26,7 +26,6 @@ import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityStackInstance; -import forge.game.spellability.TargetRestrictions; import forge.game.zone.ZoneType; import forge.util.Aggregates; @@ -52,8 +51,7 @@ public class ChooseSourceAi extends SpellAbilityAi { } } - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { sa.resetTargets(); Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); if (sa.canTarget(opp)) { diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java index 07654174a59..dedf551ada4 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java @@ -108,7 +108,7 @@ public class ChooseTypeAi extends SpellAbilityAi { @Override protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { - boolean isCurse = sa.hasParam("IsCurse"); + boolean isCurse = sa.isCurse(); if (sa.usesTargeting()) { final List oppList = Lists.newArrayList(Iterables.filter( diff --git a/forge-ai/src/main/java/forge/ai/ability/ClashAi.java b/forge-ai/src/main/java/forge/ai/ability/ClashAi.java index b02be7b92ab..8541efdb2f7 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ClashAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ClashAi.java @@ -92,7 +92,7 @@ public class ClashAi extends SpellAbilityAi { if ("Creature".equals(valid)) { // Springjack Knight // TODO: Whirlpool Whelm also uses creature targeting but it's trickier to support - CardCollectionView aiCreats = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); + CardCollectionView aiCreats = ai.getCreaturesInPlay(); CardCollectionView oppCreats = CardLists.filter(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); Card tgt = aiCreats.isEmpty() ? ComputerUtilCard.getWorstCreatureAI(oppCreats) : ComputerUtilCard.getBestCreatureAI(aiCreats); diff --git a/forge-ai/src/main/java/forge/ai/ability/ControlGainAi.java b/forge-ai/src/main/java/forge/ai/ability/ControlGainAi.java index 32aa71bbcc1..d4cfdca8c5e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ControlGainAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ControlGainAi.java @@ -272,7 +272,16 @@ public class ControlGainAi extends SpellAbilityAi { return true; } } else { - if(sa.hasParam("TargetingPlayer") || (!this.canPlayAI(ai, sa) && mandatory)) { + if (sa.hasParam("TargetingPlayer") || (!this.canPlayAI(ai, sa) && mandatory)) { + if (sa.getTargetRestrictions().canOnlyTgtOpponent()) { + List oppList = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + if (oppList.isEmpty()) { + return false; + } + sa.getTargets().add(Aggregates.random(oppList)); + return true; + } + List list = CardLists.getTargetableCards(ai.getCardsIn(ZoneType.Battlefield), sa); if (list.isEmpty()) { return false; diff --git a/forge-ai/src/main/java/forge/ai/ability/CopyPermanentAi.java b/forge-ai/src/main/java/forge/ai/ability/CopyPermanentAi.java index f5a60501da9..4cc13b47baa 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CopyPermanentAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CopyPermanentAi.java @@ -128,19 +128,25 @@ public class CopyPermanentAi extends SpellAbilityAi { final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa); final boolean canCopyLegendary = sa.hasParam("NonLegendary"); - // //// - // Targeting if (sa.usesTargeting()) { sa.resetTargets(); CardCollection list = new CardCollection(CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa)); - list = CardLists.filter(list, Predicates.not(CardPredicates.isRemAIDeck())); //Nothing to target if (list.isEmpty()) { return false; } - + + CardCollection betterList = CardLists.filter(list, Predicates.not(CardPredicates.isRemAIDeck())); + if (betterList.isEmpty()) { + if (!mandatory) { + return false; + } + } else { + list = betterList; + } + // Saheeli Rai + Felidar Guardian combo support if ("Saheeli Rai".equals(sourceName)) { CardCollection felidarGuardian = CardLists.filter(list, CardPredicates.nameEquals("Felidar Guardian")); @@ -154,7 +160,7 @@ public class CopyPermanentAi extends SpellAbilityAi { // target loop while (sa.canAddMoreTarget()) { if (list.isEmpty()) { - if (!sa.isTargetNumberValid() || (sa.getTargets().size() == 0)) { + if (!sa.isTargetNumberValid() || sa.getTargets().size() == 0) { sa.resetTargets(); return false; } else { diff --git a/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java index c24df2a5c39..000c52bc32c 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java @@ -16,7 +16,6 @@ import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; import forge.game.spellability.Spell; import forge.game.spellability.SpellAbility; -import forge.game.spellability.TargetRestrictions; import forge.util.MyRandom; public class CopySpellAbilityAi extends SpellAbilityAi { @@ -58,8 +57,7 @@ public class CopySpellAbilityAi extends SpellAbilityAi { } } - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { // Filter AI-specific targets if provided if ("OnlyOwned".equals(sa.getParam("AITgts"))) { if (!top.getActivatingPlayer().equals(aiPlayer)) { diff --git a/forge-ai/src/main/java/forge/ai/ability/CounterAi.java b/forge-ai/src/main/java/forge/ai/ability/CounterAi.java index b93c01d40a3..7b5beebb67b 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CounterAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CounterAi.java @@ -27,7 +27,6 @@ import forge.game.cost.CostSacrifice; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityStackInstance; -import forge.game.spellability.TargetRestrictions; import forge.game.zone.ZoneType; import forge.util.MyRandom; @@ -63,8 +62,7 @@ public class CounterAi extends SpellAbilityAi { } } - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { final SpellAbility topSA = ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa); if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || topSA.getActivatingPlayer() == ai || ai.getAllies().contains(topSA.getActivatingPlayer())) { @@ -246,10 +244,9 @@ public class CounterAi extends SpellAbilityAi { @Override protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { - final TargetRestrictions tgt = sa.getTargetRestrictions(); final Game game = ai.getGame(); - if (tgt != null) { + if (sa.usesTargeting()) { if (game.getStack().isEmpty()) { return false; } diff --git a/forge-ai/src/main/java/forge/ai/ability/CountersMoveAi.java b/forge-ai/src/main/java/forge/ai/ability/CountersMoveAi.java index a43320c7922..6c8699fbf87 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CountersMoveAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CountersMoveAi.java @@ -83,7 +83,7 @@ public class CountersMoveAi extends SpellAbilityAi { } // something you can't block, try to reduce its attack - if (!ComputerUtilCard.canBeBlockedProfitably(ai, cpy)) { + if (!ComputerUtilCard.canBeBlockedProfitably(ai, cpy, false)) { return true; } } diff --git a/forge-ai/src/main/java/forge/ai/ability/CountersPutAi.java b/forge-ai/src/main/java/forge/ai/ability/CountersPutAi.java index 18f216f31b1..7de981a9c22 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CountersPutAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CountersPutAi.java @@ -442,7 +442,7 @@ public class CountersPutAi extends CountersAi { } } - if ("AlwaysAtOppEOT".equals(logic)) { + if ("AtOppEOT".equals(logic)) { if (ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn().equals(ai)) { return true; } diff --git a/forge-ai/src/main/java/forge/ai/ability/DamageAiBase.java b/forge-ai/src/main/java/forge/ai/ability/DamageAiBase.java index c21c297fe62..05d98d165f7 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamageAiBase.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamageAiBase.java @@ -76,8 +76,8 @@ public abstract class DamageAiBase extends SpellAbilityAi { Card hostcard = sa.getHostCard(); for (Trigger trig : hostcard.getTriggers()) { if (trig.getMode() == TriggerType.DamageDone) { - if (("Opponent".equals(trig.getParam("ValidTarget"))) - && (!"True".equals(trig.getParam("CombatDamage")))) { + if ("Opponent".equals(trig.getParam("ValidTarget")) + && !"True".equals(trig.getParam("CombatDamage"))) { return true; } } @@ -119,7 +119,7 @@ public abstract class DamageAiBase extends SpellAbilityAi { PhaseHandler phase = game.getPhaseHandler(); // If this is a spell, cast it instead of discarding if ((phase.is(PhaseType.END_OF_TURN) || phase.is(PhaseType.MAIN2)) - && phase.isPlayerTurn(comp) && (hand.size() > comp.getMaxHandSize())) { + && phase.isPlayerTurn(comp) && hand.size() > comp.getMaxHandSize()) { return true; } diff --git a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java index 580509510e0..7e310dec65e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java @@ -448,7 +448,8 @@ public class DamageDealAi extends DamageAiBase { // We can hurt a planeswalker, so rank the one which is the best target if (!hPlay.isEmpty() && pl.isOpponentOf(ai) && activator.equals(ai)) { - return ComputerUtilCard.getBestPlaneswalkerToDamage(hPlay); + Card pw = ComputerUtilCard.getBestPlaneswalkerToDamage(hPlay); + return pw == null && mandatory ? hPlay.get(0) : pw; } return null; @@ -566,7 +567,7 @@ public class DamageDealAi extends DamageAiBase { TargetChoices tcs = sa.getTargets(); // Do not use if would kill self - if (("SelfDamage".equals(logic)) && (ai.getLife() <= Integer.parseInt(source.getSVar("SelfDamageAmount")))) { + if ("SelfDamage".equals(logic) && ai.getLife() <= Integer.parseInt(source.getSVar("SelfDamageAmount"))) { return false; } @@ -713,7 +714,7 @@ public class DamageDealAi extends DamageAiBase { } } - if (freePing && sa.canTarget(enemy) && (!avoidTargetP(ai, sa))) { + if (freePing && sa.canTarget(enemy) && !avoidTargetP(ai, sa)) { tcs.add(enemy); if (divided) { sa.addDividedAllocation(enemy, dmg); diff --git a/forge-ai/src/main/java/forge/ai/ability/DamageEachAi.java b/forge-ai/src/main/java/forge/ai/ability/DamageEachAi.java index 2471f3c52b0..59209d27f67 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamageEachAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamageEachAi.java @@ -21,13 +21,12 @@ public class DamageEachAi extends DamageAiBase { Player weakestOpp = targetableOpps.min(PlayerPredicates.compareByLife()); if (sa.usesTargeting() && weakestOpp != null) { + if ("MadSarkhanUltimate".equals(logic) && !SpecialCardAi.SarkhanTheMad.considerUltimate(ai, sa, weakestOpp)) { + return false; + } sa.resetTargets(); sa.getTargets().add(weakestOpp); } - - if ("MadSarkhanUltimate".equals(logic)) { - return SpecialCardAi.SarkhanTheMad.considerUltimate(ai, sa, weakestOpp); - } final String damage = sa.getParam("NumDmg"); final int iDmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa); diff --git a/forge-ai/src/main/java/forge/ai/ability/DebuffAi.java b/forge-ai/src/main/java/forge/ai/ability/DebuffAi.java index 6acb3b2cc2a..832c1313dce 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DebuffAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DebuffAi.java @@ -91,8 +91,7 @@ public class DebuffAi extends SpellAbilityAi { @Override public boolean chkAIDrawback(SpellAbility sa, Player ai) { if (!sa.usesTargeting()) { - // TODO - copied from AF_Pump.pumpDrawbackAI() - what should be - // here? + // TODO - copied from AF_Pump.pumpDrawbackAI() - what should be here? } else { return debuffTgtAI(ai, sa, sa.hasParam("Keywords") ? Arrays.asList(sa.getParam("Keywords").split(" & ")) : null, false); } diff --git a/forge-ai/src/main/java/forge/ai/ability/DestroyAi.java b/forge-ai/src/main/java/forge/ai/ability/DestroyAi.java index f5b182846ce..7113db74e6f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DestroyAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DestroyAi.java @@ -371,7 +371,7 @@ public class DestroyAi extends SpellAbilityAi { break; } } else { - break; + return true; } } else { Card c = ComputerUtilCard.getBestAI(preferred); @@ -380,7 +380,7 @@ public class DestroyAi extends SpellAbilityAi { } } - while (sa.canAddMoreTarget()) { + while (!sa.isMinTargetChosen()) { if (list.isEmpty()) { break; } else { diff --git a/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java b/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java index 17701bc2d77..1daa3a9991e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java @@ -148,13 +148,13 @@ public class DestroyAllAi extends SpellAbilityAi { for (Card att : opponent.getCreaturesInPlay()) { if (ComputerUtilCombat.canAttackNextTurn(att, ai)) { combat.addAttacker(att, ai); - containsAttacker = containsAttacker | opplist.contains(att); + containsAttacker = containsAttacker || opplist.contains(att); } } if (!containsAttacker) { return false; } - AiBlockController block = new AiBlockController(ai); + AiBlockController block = new AiBlockController(ai, false); block.assignBlockersForCombat(combat); if (ComputerUtilCombat.lifeInSeriousDanger(ai, combat)) { diff --git a/forge-ai/src/main/java/forge/ai/ability/DigAi.java b/forge-ai/src/main/java/forge/ai/ability/DigAi.java index e16d8ce48df..9ae979ce786 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DigAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DigAi.java @@ -47,7 +47,7 @@ public class DigAi extends SpellAbilityAi { if (sa.usesTargeting()) { sa.resetTargets(); - if (!opp.canBeTargetedBy(sa)) { + if (!sa.canTarget(opp)) { return false; } sa.getTargets().add(opp); @@ -61,7 +61,7 @@ public class DigAi extends SpellAbilityAi { if ("Never".equals(sa.getParam("AILogic"))) { return false; - } else if ("AtOppEndOfTurn".equals(sa.getParam("AILogic"))) { + } else if ("AtOppEOT".equals(sa.getParam("AILogic"))) { if (!(game.getPhaseHandler().getNextTurn() == ai && game.getPhaseHandler().is(PhaseType.END_OF_TURN))) { return false; } diff --git a/forge-ai/src/main/java/forge/ai/ability/DigMultipleAi.java b/forge-ai/src/main/java/forge/ai/ability/DigMultipleAi.java index 76cd8df5362..08a6c192914 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DigMultipleAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DigMultipleAi.java @@ -40,7 +40,7 @@ public class DigMultipleAi extends SpellAbilityAi { if ("Never".equals(sa.getParam("AILogic"))) { return false; - } else if ("AtOppEndOfTurn".equals(sa.getParam("AILogic"))) { + } else if ("AtOppEOT".equals(sa.getParam("AILogic"))) { if (!(game.getPhaseHandler().getNextTurn() == ai && game.getPhaseHandler().is(PhaseType.END_OF_TURN))) { return false; } diff --git a/forge-ai/src/main/java/forge/ai/ability/DigUntilAi.java b/forge-ai/src/main/java/forge/ai/ability/DigUntilAi.java index 331acd2a61a..dc11d808114 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DigUntilAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DigUntilAi.java @@ -130,8 +130,7 @@ public class DigUntilAi extends SpellAbilityAi { if ("OathOfDruids".equals(logic)) { final List creaturesInLibrary = CardLists.filter(player.getCardsIn(ZoneType.Library), CardPredicates.Presets.CREATURES); - final List creaturesInBattlefield = - CardLists.filter(player.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); + final List creaturesInBattlefield = player.getCreaturesInPlay(); // if there are at least 3 creatures in library, // or none in play with one in library, oath return creaturesInLibrary.size() > 2 diff --git a/forge-ai/src/main/java/forge/ai/ability/DrawAi.java b/forge-ai/src/main/java/forge/ai/ability/DrawAi.java index 48a3dcce9a0..9d7f339bf7e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DrawAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DrawAi.java @@ -140,7 +140,7 @@ public class DrawAi extends SpellAbilityAi { // LifeLessThan logic presupposes activation as soon as possible in an // attempt to save the AI from dying return true; - } else if (logic.equals("AlwaysAtOppEOT")) { + } else if (logic.equals("AtOppEOT")) { return ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn().equals(ai); } else if (logic.equals("RespondToOwnActivation")) { return !ai.getGame().getStack().isEmpty() && ai.getGame().getStack().peekAbility().getHostCard().equals(sa.getHostCard()); @@ -176,7 +176,7 @@ public class DrawAi extends SpellAbilityAi { @Override public boolean chkAIDrawback(SpellAbility sa, Player ai) { - return targetAI(ai, sa, false); + return targetAI(ai, sa, sa.isTrigger() && sa.getHostCard().isInPlay()); } /** diff --git a/forge-ai/src/main/java/forge/ai/ability/EncodeAi.java b/forge-ai/src/main/java/forge/ai/ability/EncodeAi.java index 3f68bd73ed8..6627b3847c0 100644 --- a/forge-ai/src/main/java/forge/ai/ability/EncodeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/EncodeAi.java @@ -61,7 +61,6 @@ public final class EncodeAi extends SpellAbilityAi { public boolean chkAIDrawback(SpellAbility sa, Player ai) { return true; } - /* * (non-Javadoc) diff --git a/forge-ai/src/main/java/forge/ai/ability/FightAi.java b/forge-ai/src/main/java/forge/ai/ability/FightAi.java index 4b8771b2d2c..d5e36f5a8bc 100644 --- a/forge-ai/src/main/java/forge/ai/ability/FightAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/FightAi.java @@ -66,7 +66,7 @@ public class FightAi extends SpellAbilityAi { } } if (fighter1List.isEmpty()) { - return true; // FIXME: shouldn't this return "false" if nothing found? + return false; } Card fighter1 = fighter1List.get(0); for (Card humanCreature : humCreatures) { diff --git a/forge-ai/src/main/java/forge/ai/ability/FlipACoinAi.java b/forge-ai/src/main/java/forge/ai/ability/FlipACoinAi.java index d41ac5a2aea..efa2a43fdb3 100644 --- a/forge-ai/src/main/java/forge/ai/ability/FlipACoinAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/FlipACoinAi.java @@ -54,7 +54,7 @@ public class FlipACoinAi extends SpellAbilityAi { return false; } } - return true; + return sa.isTargetNumberValid(); } @Override diff --git a/forge-ai/src/main/java/forge/ai/ability/GameLossAi.java b/forge-ai/src/main/java/forge/ai/ability/GameLossAi.java index 762db5c2189..7dafdfe4b64 100644 --- a/forge-ai/src/main/java/forge/ai/ability/GameLossAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/GameLossAi.java @@ -17,11 +17,10 @@ public class GameLossAi extends SpellAbilityAi { if (sa.usesTargeting()) { sa.resetTargets(); sa.getTargets().add(opp); + return true; } - // In general, don't return true. - // But this card wins the game, I can make an exception for that - return true; + return false; } @Override @@ -35,7 +34,7 @@ public class GameLossAi extends SpellAbilityAi { loser = ai.getGame().getCombat().getDefenderPlayerByAttacker(sa.getHostCard()); } - if (!mandatory && loser.cantLose()) { + if (!mandatory && (loser == ai || loser.cantLose())) { return false; } diff --git a/forge-ai/src/main/java/forge/ai/ability/GoadAi.java b/forge-ai/src/main/java/forge/ai/ability/GoadAi.java index b2d8b30b9ef..cf8c8de79fe 100644 --- a/forge-ai/src/main/java/forge/ai/ability/GoadAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/GoadAi.java @@ -65,7 +65,7 @@ public class GoadAi extends SpellAbilityAi { return false; } // select only creatures AI can block - return ComputerUtilCard.canBeBlockedProfitably(ai, c); + return ComputerUtilCard.canBeBlockedProfitably(ai, c, false); } }); diff --git a/forge-ai/src/main/java/forge/ai/ability/LifeExchangeAi.java b/forge-ai/src/main/java/forge/ai/ability/LifeExchangeAi.java index 6ad44da50f6..71cdad4a7be 100644 --- a/forge-ai/src/main/java/forge/ai/ability/LifeExchangeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/LifeExchangeAi.java @@ -1,8 +1,9 @@ package forge.ai.ability; -import forge.ai.AiAttackController; import forge.ai.SpellAbilityAi; import forge.game.player.Player; +import forge.game.player.PlayerCollection; +import forge.game.player.PlayerPredicates; import forge.game.spellability.SpellAbility; import forge.util.MyRandom; @@ -18,14 +19,15 @@ public class LifeExchangeAi extends SpellAbilityAi { */ @Override protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) { - final int myLife = aiPlayer.getLife(); - Player opponent = AiAttackController.choosePreferredDefenderPlayer(aiPlayer); - final int hLife = opponent.getLife(); - if (!aiPlayer.canGainLife()) { return false; } + final int myLife = aiPlayer.getLife(); + final PlayerCollection targetableOpps = aiPlayer.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + final Player opponent = targetableOpps.max(PlayerPredicates.compareByLife()); + final int hLife = opponent == null ? 0 : opponent.getLife(); + // prevent run-away activations - first time will always return true boolean chance = MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); @@ -36,24 +38,23 @@ public class LifeExchangeAi extends SpellAbilityAi { */ if (sa.usesTargeting()) { sa.resetTargets(); - if (opponent.canBeTargetedBy(sa)) { + if (opponent != null && opponent.canLoseLife()) { // never target self, that would be silly for exchange sa.getTargets().add(opponent); - if (!opponent.canLoseLife()) { - return false; - } + } else { + return false; } } // if life is in danger, always activate - if ((myLife < 5) && (hLife > myLife)) { + if (myLife < 5 && hLife > myLife) { return true; } // cost includes sacrifice probably, so make sure it's worth it chance &= (hLife > (myLife + 8)); - return ((MyRandom.getRandom().nextFloat() < .6667) && chance); + return MyRandom.getRandom().nextFloat() < .6667 && chance; } /** @@ -70,13 +71,16 @@ public class LifeExchangeAi extends SpellAbilityAi { * @return a boolean. */ @Override - protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa, - final boolean mandatory) { - Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); + protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa, final boolean mandatory) { + PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + Player opp = targetableOpps.max(PlayerPredicates.compareByLife()); if (sa.usesTargeting()) { sa.resetTargets(); if (sa.canTarget(opp) && (mandatory || ai.getLife() < opp.getLife())) { sa.getTargets().add(opp); + if (sa.canAddMoreTarget()) { + sa.getTargets().add(ai); + } } else { return false; } diff --git a/forge-ai/src/main/java/forge/ai/ability/LifeExchangeVariantAi.java b/forge-ai/src/main/java/forge/ai/ability/LifeExchangeVariantAi.java index f10c29d4ccd..f5f57169981 100644 --- a/forge-ai/src/main/java/forge/ai/ability/LifeExchangeVariantAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/LifeExchangeVariantAi.java @@ -149,8 +149,7 @@ public class LifeExchangeVariantAi extends SpellAbilityAi { * @return a boolean. */ @Override - protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa, - final boolean mandatory) { + protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa, final boolean mandatory) { Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); if (sa.usesTargeting()) { sa.resetTargets(); diff --git a/forge-ai/src/main/java/forge/ai/ability/LifeLoseAi.java b/forge-ai/src/main/java/forge/ai/ability/LifeLoseAi.java index 29b295018a8..41e62d105fb 100644 --- a/forge-ai/src/main/java/forge/ai/ability/LifeLoseAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/LifeLoseAi.java @@ -38,7 +38,7 @@ public class LifeLoseAi extends SpellAbilityAi { SpellAbility root = sa.getRootAbility(); if (root.getXManaCostPaid() != null) { amount = root.getXManaCostPaid(); - } else { + } else if (root.getPayCosts() != null && root.getPayCosts().hasXInAnyCostPart()) { // Set PayX here to maximum value. final int xPay = ComputerUtilCost.getMaxXValue(sa, ai); root.setXManaCostPaid(xPay); diff --git a/forge-ai/src/main/java/forge/ai/ability/LifeSetAi.java b/forge-ai/src/main/java/forge/ai/ability/LifeSetAi.java index ef07915ded9..fbe6b154cfd 100644 --- a/forge-ai/src/main/java/forge/ai/ability/LifeSetAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/LifeSetAi.java @@ -1,15 +1,21 @@ package forge.ai.ability; +import com.google.common.collect.Iterables; + import forge.ai.ComputerUtilAbility; import forge.ai.ComputerUtilCost; import forge.ai.SpellAbilityAi; import forge.game.ability.AbilityUtils; import forge.game.card.Card; +import forge.game.card.CardPredicates; import forge.game.card.CounterEnumType; import forge.game.phase.PhaseType; import forge.game.player.Player; +import forge.game.player.PlayerCollection; +import forge.game.player.PlayerPredicates; import forge.game.spellability.SpellAbility; import forge.game.spellability.TargetRestrictions; +import forge.game.zone.ZoneType; import forge.util.MyRandom; public class LifeSetAi extends SpellAbilityAi { @@ -17,14 +23,11 @@ public class LifeSetAi extends SpellAbilityAi { @Override protected boolean canPlayAI(Player ai, SpellAbility sa) { final int myLife = ai.getLife(); - final Player opponent = ai.getStrongestOpponent(); - final int hlife = opponent.getLife(); + final PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + final Player opponent = targetableOpps.max(PlayerPredicates.compareByLife()); + final int hlife = opponent == null ? 0 : opponent.getLife(); final String amountStr = sa.getParam("LifeAmount"); - if (!ai.canGainLife()) { - return false; - } - // Don't use setLife before main 2 if possible if (ai.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2) && !sa.hasParam("ActivationPhases")) { @@ -55,20 +58,20 @@ public class LifeSetAi extends SpellAbilityAi { if (tgt != null) { sa.resetTargets(); if (tgt.canOnlyTgtOpponent()) { - sa.getTargets().add(opponent); // if we can only target the human, and the Human's life // would go up, don't play it. // possibly add a combo here for Magister Sphinx and // Higedetsu's (sp?) Second Rite - if ((amount > hlife) || !opponent.canLoseLife()) { + if (opponent == null || amount > hlife || !opponent.canLoseLife()) { return false; } + sa.getTargets().add(opponent); } else { - if ((amount > myLife) && (myLife <= 10)) { + if (amount > myLife && myLife <= 10 && ai.canGainLife()) { sa.getTargets().add(ai); } else if (hlife > amount) { sa.getTargets().add(opponent); - } else if (amount > myLife) { + } else if (amount > myLife && ai.canGainLife()) { sa.getTargets().add(ai); } else { return false; @@ -90,18 +93,19 @@ public class LifeSetAi extends SpellAbilityAi { } // if life is in danger, always activate - if ((myLife < 3) && (amount > myLife)) { + if (myLife < 3 && amount > myLife && ai.canGainLife()) { return true; } - return ((MyRandom.getRandom().nextFloat() < .6667) && chance); + return MyRandom.getRandom().nextFloat() < .6667 && chance; } @Override protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { final int myLife = ai.getLife(); - final Player opponent = ai.getStrongestOpponent(); - final int hlife = opponent.getLife(); + final PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + final Player opponent = targetableOpps.max(PlayerPredicates.compareByLife()); + final int hlife = opponent == null ? 0 : opponent.getLife(); final Card source = sa.getHostCard(); final String sourceName = ComputerUtilAbility.getAbilitySourceName(sa); @@ -120,11 +124,11 @@ public class LifeSetAi extends SpellAbilityAi { // special cases when amount can't be calculated without targeting first if (amount == 0 && "TargetedPlayer$StartingLife/HalfDown".equals(source.getSVar(amountStr))) { // e.g. Torgaar, Famine Incarnate - return doHalfStartingLifeLogic(ai, opponent, sa); + return doHalfStartingLifeLogic(ai, opponent, sa) || mandatory; } if (sourceName.equals("Eternity Vessel") - && (opponent.isCardInPlay("Vampire Hexmage") || (source.getCounters(CounterEnumType.CHARGE) == 0))) { + && (Iterables.any(ai.getOpponents().getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Vampire Hexmage")) || (source.getCounters(CounterEnumType.CHARGE) == 0))) { return false; } @@ -134,13 +138,16 @@ public class LifeSetAi extends SpellAbilityAi { if (tgt != null) { sa.resetTargets(); if (tgt.canOnlyTgtOpponent()) { + if (opponent == null) { + return false; + } sa.getTargets().add(opponent); } else { if (amount > myLife && myLife <= 10) { sa.getTargets().add(ai); } else if (hlife > amount) { sa.getTargets().add(opponent); - } else if (amount > myLife) { + } else if (amount > myLife || mandatory) { sa.getTargets().add(ai); } else { return false; @@ -153,9 +160,9 @@ public class LifeSetAi extends SpellAbilityAi { private boolean doHalfStartingLifeLogic(Player ai, Player opponent, SpellAbility sa) { int aiAmount = ai.getStartingLife() / 2; - int oppAmount = opponent.getStartingLife() / 2; + int oppAmount = opponent == null ? 0 : opponent.getStartingLife() / 2; int aiLife = ai.getLife(); - int oppLife = opponent.getLife(); + int oppLife = opponent == null ? 0 : opponent.getLife(); sa.resetTargets(); diff --git a/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java b/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java index c4abbd58167..305cece5cdd 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java @@ -14,7 +14,9 @@ import forge.ai.PlayerControllerAi; import forge.ai.SpellAbilityAi; import forge.card.ColorSet; import forge.card.MagicColor; +import forge.card.mana.ManaAtom; import forge.card.mana.ManaCost; +import forge.game.GlobalRuleChange; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardCollection; @@ -25,6 +27,8 @@ import forge.game.card.CounterType; import forge.game.cost.CostPart; import forge.game.cost.CostRemoveCounter; import forge.game.keyword.Keyword; +import forge.game.mana.Mana; +import forge.game.mana.ManaPool; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; @@ -61,6 +65,9 @@ public class ManaEffectAi extends SpellAbilityAi { */ @Override protected boolean checkPhaseRestrictions(Player ai, SpellAbility sa, PhaseHandler ph) { + if (ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn() == ai && canRampPool(ai, sa.getHostCard())) { + return true; + } if (!ph.is(PhaseType.MAIN2) || !ComputerUtil.activateForCost(sa, ai)) { return false; } @@ -79,6 +86,8 @@ public class ManaEffectAi extends SpellAbilityAi { protected boolean checkPhaseRestrictions(Player ai, SpellAbility sa, PhaseHandler ph, String logic) { if (logic.startsWith("ManaRitual")) { return ph.is(PhaseType.MAIN2, ai) || ph.is(PhaseType.MAIN1, ai); + } else if ("AtOppEOT".equals(logic)) { + return !ai.getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.manaBurn) && ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn() == ai; } return super.checkPhaseRestrictions(ai, sa, ph, logic); } @@ -95,9 +104,14 @@ public class ManaEffectAi extends SpellAbilityAi { return true; // handled elsewhere, does not meet the standard requirements } + PhaseHandler ph = ai.getGame().getPhaseHandler(); + boolean moreManaNextTurn = false; + if (ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn() == ai && canRampPool(ai, sa.getHostCard())) { + moreManaNextTurn = true; + } + return sa.getPayCosts().hasNoManaCost() && sa.getPayCosts().isReusuableResource() - && sa.getSubAbility() == null && ComputerUtil.playImmediately(ai, sa); - // return super.checkApiLogic(ai, sa); + && sa.getSubAbility() == null && (ComputerUtil.playImmediately(ai, sa) || moreManaNextTurn); } /** @@ -244,4 +258,18 @@ public class ManaEffectAi extends SpellAbilityAi { // TODO: this will probably still waste the card from time to time. Somehow improve detection of castable material. return castableSpells.size() > 0; } + + private boolean canRampPool(Player ai, Card source) { + ManaPool mp = ai.getManaPool(); + Mana test = null; + if (mp.isEmpty()) { + test = new Mana((byte) ManaAtom.COLORLESS, source, null); + mp.addMana(test, false); + } + boolean lose = mp.willManaBeLostAtEndOfPhase(); + if (test != null) { + mp.removeMana(test, false); + } + return !lose; + } } diff --git a/forge-ai/src/main/java/forge/ai/ability/MillAi.java b/forge-ai/src/main/java/forge/ai/ability/MillAi.java index f6802577a72..ccaf7fcef14 100644 --- a/forge-ai/src/main/java/forge/ai/ability/MillAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/MillAi.java @@ -146,13 +146,13 @@ public class MillAi extends SpellAbilityAi { // can't target opponent? if (list.isEmpty()) { - if (mandatory && sa.canTarget(ai)) { + if (mandatory && !sa.isTargetNumberValid() && sa.canTarget(ai)) { sa.getTargets().add(ai); return true; } // TODO Obscure case when you know what your top card is so you might? // want to mill yourself here - return false; + return sa.isTargetNumberValid(); } // select Player which would cause the most damage diff --git a/forge-ai/src/main/java/forge/ai/ability/MustBlockAi.java b/forge-ai/src/main/java/forge/ai/ability/MustBlockAi.java index 4e6a51dcfde..288b8f79163 100644 --- a/forge-ai/src/main/java/forge/ai/ability/MustBlockAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/MustBlockAi.java @@ -5,7 +5,6 @@ import java.util.Map; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import forge.ai.AiCardMemory; import forge.ai.ComputerUtilCard; @@ -15,14 +14,12 @@ import forge.game.Game; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardLists; -import forge.game.card.CardPredicates; import forge.game.combat.Combat; import forge.game.combat.CombatUtil; import forge.game.keyword.Keyword; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.spellability.SpellAbility; -import forge.game.zone.ZoneType; public class MustBlockAi extends SpellAbilityAi { @@ -76,7 +73,7 @@ public class MustBlockAi extends SpellAbilityAi { return false; } - Card attacker = null; + Card attacker = source; if (sa.hasParam("DefinedAttacker")) { final List cards = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedAttacker"), sa); if (cards.isEmpty()) { @@ -86,18 +83,12 @@ public class MustBlockAi extends SpellAbilityAi { attacker = cards.get(0); } - if (attacker == null) { - attacker = source; - } - - final Card definedAttacker = attacker; - boolean chance = false; if (sa.usesTargeting()) { - final List list = determineGoodBlockers(definedAttacker, ai, ai.getWeakestOpponent(), sa, true,true); + final List list = determineGoodBlockers(attacker, ai, ai.getWeakestOpponent(), sa, true, true); if (list.isEmpty()) { - return false; + return sa.isTargetNumberValid(); } final Card blocker = ComputerUtilCard.getBestCreatureAI(list); if (blocker == null) { @@ -160,8 +151,7 @@ public class MustBlockAi extends SpellAbilityAi { private List determineGoodBlockers(final Card attacker, final Player ai, Player defender, SpellAbility sa, final boolean onlyLethal, final boolean testTapped) { - List list = Lists.newArrayList(); - list = CardLists.filter(defender.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); + List list = defender.getCreaturesInPlay(); if (sa.usesTargeting()) { list = CardLists.getTargetableCards(list, sa); @@ -187,7 +177,7 @@ public class MustBlockAi extends SpellAbilityAi { List better = determineBlockerFromList(attacker, ai, options, sa, false, false); if (!better.isEmpty()) { - return Iterables.getFirst(options, null); + return Iterables.getFirst(better, null); } return Iterables.getFirst(options, null); diff --git a/forge-ai/src/main/java/forge/ai/ability/PermanentCreatureAi.java b/forge-ai/src/main/java/forge/ai/ability/PermanentCreatureAi.java index 0e95d23db25..924c8e86784 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PermanentCreatureAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PermanentCreatureAi.java @@ -140,7 +140,7 @@ public class PermanentCreatureAi extends PermanentAi { boolean hasAmbushAI = card.hasSVar("AmbushAI"); boolean defOnlyAmbushAI = hasAmbushAI && "BlockOnly".equals(card.getSVar("AmbushAI")); boolean hasFloatMana = ai.getManaPool().totalMana() > 0; - boolean willDiscardNow = isOwnEOT && ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize(); + boolean willDiscardNow = isOwnEOT && !ai.isUnlimitedHandSize() && ai.getCardsIn(ZoneType.Hand).size() > ai.getMaxHandSize(); boolean willDieNow = combat != null && ComputerUtilCombat.lifeInSeriousDanger(ai, combat); boolean wantToCastInMain1 = ph.is(PhaseType.MAIN1, ai) && ComputerUtil.castPermanentInMain1(ai, sa); boolean isCommander = card.isCommander(); diff --git a/forge-ai/src/main/java/forge/ai/ability/PhasesAi.java b/forge-ai/src/main/java/forge/ai/ability/PhasesAi.java index 8973d02888a..a033ce0b613 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PhasesAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PhasesAi.java @@ -63,7 +63,7 @@ public class PhasesAi extends SpellAbilityAi { return true; } else if (mandatory) { // not enough preferred targets, but mandatory so keep going: - return phasesUnpreferredTargeting(aiPlayer.getGame(), sa, mandatory); + return sa.isTargetNumberValid() || phasesUnpreferredTargeting(aiPlayer.getGame(), sa, mandatory); } return false; diff --git a/forge-ai/src/main/java/forge/ai/ability/PoisonAi.java b/forge-ai/src/main/java/forge/ai/ability/PoisonAi.java index b9547f2e875..d6a65513f4e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PoisonAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PoisonAi.java @@ -25,8 +25,7 @@ public class PoisonAi extends SpellAbilityAi { */ @Override protected boolean checkPhaseRestrictions(final Player ai, final SpellAbility sa, final PhaseHandler ph) { - return !ph.getPhase().isBefore(PhaseType.MAIN2) - || sa.hasParam("ActivationPhases"); + return !ph.getPhase().isBefore(PhaseType.MAIN2) || sa.hasParam("ActivationPhases"); } /* diff --git a/forge-ai/src/main/java/forge/ai/ability/PowerExchangeAi.java b/forge-ai/src/main/java/forge/ai/ability/PowerExchangeAi.java index fa362f97a0d..04f3e23379a 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PowerExchangeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PowerExchangeAi.java @@ -31,11 +31,10 @@ public class PowerExchangeAi extends SpellAbilityAi { List list = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, sa.getHostCard(), sa); - // AI won't try to grab cards that are filtered out of AI decks on purpose list = CardLists.filter(list, new Predicate() { @Override public boolean apply(final Card c) { - return !ComputerUtilCard.isCardRemAIDeck(c) && c.canBeTargetedBy(sa) && c.getController() != ai; + return c.canBeTargetedBy(sa) && c.getController() != ai; } }); CardLists.sortByPowerAsc(list); diff --git a/forge-ai/src/main/java/forge/ai/ability/ProtectAllAi.java b/forge-ai/src/main/java/forge/ai/ability/ProtectAllAi.java index 69765ce7717..6352447e814 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ProtectAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ProtectAllAi.java @@ -26,7 +26,6 @@ public class ProtectAllAi extends SpellAbilityAi { return false; } // protectAllCanPlayAI() - @Override protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) { return true; diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java b/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java index e240f51cd27..a95a44b904a 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java @@ -23,7 +23,6 @@ import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.spellability.SpellAbility; -import forge.game.spellability.TargetRestrictions; import forge.game.zone.ZoneType; public class PumpAllAi extends PumpAiBase { @@ -57,19 +56,20 @@ public class PumpAllAi extends PumpAiBase { } } - final TargetRestrictions tgt = sa.getTargetRestrictions(); final Player opp = ai.getStrongestOpponent(); - if (tgt != null && sa.canTarget(opp) && sa.isCurse()) { - sa.resetTargets(); - sa.getTargets().add(opp); - return true; - } - - if (tgt != null && sa.canTarget(ai) && !sa.isCurse()) { - sa.resetTargets(); - sa.getTargets().add(ai); - return true; + if (sa.usesTargeting()) { + if (sa.canTarget(opp) && sa.isCurse()) { + sa.resetTargets(); + sa.getTargets().add(opp); + return true; + } + + if (sa.canTarget(ai) && !sa.isCurse()) { + sa.resetTargets(); + sa.getTargets().add(ai); + return true; + } } final int power = AbilityUtils.calculateAmount(source, sa.getParam("NumAtt"), sa); diff --git a/forge-ai/src/main/java/forge/ai/ability/RearrangeTopOfLibraryAi.java b/forge-ai/src/main/java/forge/ai/ability/RearrangeTopOfLibraryAi.java index 408d912f76b..b446d81c98c 100644 --- a/forge-ai/src/main/java/forge/ai/ability/RearrangeTopOfLibraryAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/RearrangeTopOfLibraryAi.java @@ -53,7 +53,7 @@ public class RearrangeTopOfLibraryAi extends SpellAbilityAi { PlayerCollection targetableOpps = aiPlayer.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); Player opp = targetableOpps.min(PlayerPredicates.compareByLife()); final boolean canTgtAI = sa.canTarget(aiPlayer); - final boolean canTgtHuman = opp != null && sa.canTarget(opp); + final boolean canTgtHuman = sa.canTarget(opp); if (canTgtHuman && canTgtAI) { // TODO: maybe some other consideration rather than random? diff --git a/forge-ai/src/main/java/forge/ai/ability/RegenerateAi.java b/forge-ai/src/main/java/forge/ai/ability/RegenerateAi.java index 5a1f1132f58..cfb749274fe 100644 --- a/forge-ai/src/main/java/forge/ai/ability/RegenerateAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/RegenerateAi.java @@ -138,12 +138,11 @@ public class RegenerateAi extends SpellAbilityAi { protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { boolean chance = false; - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt == null) { + if (sa.usesTargeting()) { + chance = regenMandatoryTarget(ai, sa, mandatory); + } else { // If there's no target on the trigger, just say yes. chance = true; - } else { - chance = regenMandatoryTarget(ai, sa, mandatory); } return chance; @@ -164,7 +163,7 @@ public class RegenerateAi extends SpellAbilityAi { return false; } - if (!mandatory && (compTargetables.size() == 0)) { + if (!mandatory && compTargetables.size() == 0) { return false; } diff --git a/forge-ai/src/main/java/forge/ai/ability/SacrificeAi.java b/forge-ai/src/main/java/forge/ai/ability/SacrificeAi.java index 5a94167b7bf..0b6f2e3ddc8 100644 --- a/forge-ai/src/main/java/forge/ai/ability/SacrificeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/SacrificeAi.java @@ -15,6 +15,8 @@ import forge.game.card.CardPredicates; import forge.game.keyword.Keyword; import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; +import forge.game.player.PlayerCollection; +import forge.game.player.PlayerPredicates; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; @@ -22,14 +24,14 @@ public class SacrificeAi extends SpellAbilityAi { @Override protected boolean canPlayAI(Player ai, SpellAbility sa) { - return sacrificeTgtAI(ai, sa); + return sacrificeTgtAI(ai, sa, false); } @Override public boolean chkAIDrawback(SpellAbility sa, Player ai) { // AI should only activate this during Human's turn - return sacrificeTgtAI(ai, sa); + return sacrificeTgtAI(ai, sa, false); } @Override @@ -48,21 +50,24 @@ public class SacrificeAi extends SpellAbilityAi { // Eventually, we can call the trigger of ETB abilities with not // mandatory as part of the checks to cast something - return sacrificeTgtAI(ai, sa) || mandatory; + return sacrificeTgtAI(ai, sa, mandatory) || mandatory; } - private boolean sacrificeTgtAI(final Player ai, final SpellAbility sa) { + private boolean sacrificeTgtAI(final Player ai, final SpellAbility sa, boolean mandatory) { final Card source = sa.getHostCard(); final boolean destroy = sa.hasParam("Destroy"); - Player opp = ai.getStrongestOpponent(); - if (sa.usesTargeting()) { - sa.resetTargets(); - if (!opp.canBeTargetedBy(sa)) { + final PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + if (targetableOpps.isEmpty()) { return false; } + final Player opp = targetableOpps.max(PlayerPredicates.compareByLife()); + sa.resetTargets(); sa.getTargets().add(opp); + if (mandatory) { + return true; + } final String valid = sa.getParam("SacValid"); String num = sa.getParamOrDefault("Amount" , "1"); final int amount = AbilityUtils.calculateAmount(source, num, sa); @@ -79,7 +84,7 @@ public class SacrificeAi extends SpellAbilityAi { for (Card c : list) { if (c.hasSVar("SacMe") && Integer.parseInt(c.getSVar("SacMe")) > 3) { - return false; + return false; } } if (!destroy) { @@ -131,7 +136,7 @@ public class SacrificeAi extends SpellAbilityAi { List humanList = null; try { - humanList = CardLists.getValidCards(opp.getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), source, sa); + humanList = CardLists.getValidCards(ai.getStrongestOpponent().getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), source, sa); } catch (NullPointerException e) { return false; } finally { diff --git a/forge-ai/src/main/java/forge/ai/ability/SetStateAi.java b/forge-ai/src/main/java/forge/ai/ability/SetStateAi.java index 91b74d2566f..8d38bd31b4e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/SetStateAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/SetStateAi.java @@ -33,6 +33,7 @@ public class SetStateAi extends SpellAbilityAi { final String mode = sa.getParam("Mode"); // turning face is most likely okay + // TODO only do this at beneficial moment (e.g. surprise during combat or morph trigger), might want to reserve mana to protect them from easy removal if ("TurnFace".equals(mode)) { return true; } @@ -208,8 +209,8 @@ public class SetStateAi extends SpellAbilityAi { // if an opponent can't block it, no need to transform (back) for (Player opp : ai.getOpponents()) { - boolean attackCard = !ComputerUtilCard.canBeBlockedProfitably(opp, original); - boolean attackTransformed = !ComputerUtilCard.canBeBlockedProfitably(opp, copy); + boolean attackCard = !ComputerUtilCard.canBeBlockedProfitably(opp, original, true); + boolean attackTransformed = !ComputerUtilCard.canBeBlockedProfitably(opp, copy, true); // both forms can attack, try to use the one with better value if (attackCard && attackTransformed) { diff --git a/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java b/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java index dd89e45ab75..bfa6105413f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java @@ -16,6 +16,8 @@ import forge.game.card.CardPredicates; import forge.game.combat.CombatUtil; import forge.game.phase.PhaseType; import forge.game.player.Player; +import forge.game.player.PlayerCollection; +import forge.game.player.PlayerPredicates; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.util.MyRandom; @@ -27,7 +29,7 @@ public class TapAllAi extends SpellAbilityAi { // or during upkeep/begin combat? final Card source = sa.getHostCard(); - final Player opp = ai.getWeakestOpponent(); + final Player opp = ai.getStrongestOpponent(); final Game game = ai.getGame(); if (game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_BEGIN)) { @@ -101,10 +103,14 @@ public class TapAllAi extends SpellAbilityAi { CardCollectionView validTappables = getTapAllTargets(valid, source, sa); if (sa.usesTargeting()) { + final PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + Player target = targetableOpps.max(PlayerPredicates.compareByLife()); + if (target == null && mandatory) { + target = ai; + } sa.resetTargets(); - Player opp = ai.getStrongestOpponent(); - sa.getTargets().add(opp); - validTappables = opp.getCardsIn(ZoneType.Battlefield); + sa.getTargets().add(target); + validTappables = target.getCardsIn(ZoneType.Battlefield); } if (mandatory) { diff --git a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java index 69ce9ce0117..9bd2f20db2c 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java @@ -33,6 +33,8 @@ import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; +import forge.game.player.PlayerCollection; +import forge.game.player.PlayerPredicates; import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; import forge.game.spellability.TargetRestrictions; @@ -260,7 +262,12 @@ public class TokenAi extends SpellAbilityAi { if (tgt != null) { sa.resetTargets(); if (tgt.canOnlyTgtOpponent()) { - sa.getTargets().add(ai.getWeakestOpponent()); + PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + if (mandatory && targetableOpps.isEmpty()) { + return false; + } + Player opp = targetableOpps.min(PlayerPredicates.compareByLife()); + sa.getTargets().add(opp); } else { sa.getTargets().add(ai); } diff --git a/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java b/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java index 9fafd25f28d..1f1e61fe286 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java @@ -10,7 +10,6 @@ import forge.game.card.CardCollectionView; import forge.game.card.CardLists; import forge.game.player.Player; import forge.game.spellability.SpellAbility; -import forge.game.spellability.TargetRestrictions; import forge.game.zone.ZoneType; import forge.util.collect.FCollection; @@ -28,8 +27,7 @@ public class TwoPilesAi extends SpellAbilityAi { final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { sa.resetTargets(); if (sa.canTarget(opp)) { sa.getTargets().add(opp); diff --git a/forge-ai/src/main/java/forge/ai/ability/UnattachAllAi.java b/forge-ai/src/main/java/forge/ai/ability/UnattachAllAi.java index 2bd45aa83ca..5a14e5962a0 100644 --- a/forge-ai/src/main/java/forge/ai/ability/UnattachAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/UnattachAllAi.java @@ -12,7 +12,6 @@ import forge.game.card.Card; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.spellability.SpellAbility; -import forge.game.spellability.TargetRestrictions; import forge.util.MyRandom; public class UnattachAllAi extends SpellAbilityAi { @@ -48,7 +47,6 @@ public class UnattachAllAi extends SpellAbilityAi { return chance; } - /* (non-Javadoc) * @see forge.card.abilityfactory.SpellAiLogic#doTriggerAINoCost(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility, boolean) */ @@ -57,8 +55,7 @@ public class UnattachAllAi extends SpellAbilityAi { final Card card = sa.getHostCard(); // Check if there are any valid targets List targets = new ArrayList<>(); - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt == null) { + if (!sa.usesTargeting()) { targets = AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam("Defined"), sa); } diff --git a/forge-ai/src/main/java/forge/ai/ability/UntapAi.java b/forge-ai/src/main/java/forge/ai/ability/UntapAi.java index cc038b3c7a4..7c4dc3329af 100644 --- a/forge-ai/src/main/java/forge/ai/ability/UntapAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/UntapAi.java @@ -6,7 +6,6 @@ import java.util.Map; import com.google.common.base.Predicate; import com.google.common.base.Predicates; -import forge.ai.AiAttackController; import forge.ai.ComputerUtil; import forge.ai.ComputerUtilAbility; import forge.ai.ComputerUtilCard; @@ -70,7 +69,6 @@ public class UntapAi extends SpellAbilityAi { } else { return untapPrefTargeting(ai, sa, false); } - } @Override @@ -125,11 +123,11 @@ public class UntapAi extends SpellAbilityAi { private static boolean untapPrefTargeting(final Player ai, final SpellAbility sa, final boolean mandatory) { final Card source = sa.getHostCard(); - Player targetController = ai; - + final PlayerCollection targetController = new PlayerCollection(); if (sa.isCurse()) { - // TODO search through all opponents, may need to check if different controllers allowed - targetController = AiAttackController.choosePreferredDefenderPlayer(ai); + targetController.addAll(ai.getOpponents()); + } else { + targetController.add(ai); } CardCollection list = CardLists.getTargetableCards(targetController.getCardsIn(ZoneType.Battlefield), sa); diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index 53df565bc54..e537b1754ca 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -8,8 +8,11 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.common.collect.Table; import forge.LobbyPlayer; +import forge.ai.AIOption; import forge.ai.LobbyPlayerAi; import forge.game.Game; import forge.game.GameEntity; @@ -54,19 +57,19 @@ public class GameCopier { public GameCopier(Game origGame) { this.origGame = origGame; } - + public Game getOriginalGame() { return origGame; } - + public Game getCopiedGame() { return gameObjectMap.getGame(); } - + public Game makeCopy() { - return makeCopy(null); + return makeCopy(null, null); } - public Game makeCopy(PhaseType advanceToPhase) { + public Game makeCopy(PhaseType advanceToPhase, Player aiPlayer) { List origPlayers = origGame.getMatch().getPlayers(); List newPlayers = new ArrayList<>(); for (RegisteredPlayer p : origPlayers) { @@ -82,8 +85,7 @@ public class GameCopier { newPlayer.setActivateLoyaltyAbilityThisTurn(origPlayer.getActivateLoyaltyAbilityThisTurn()); for (int j = 0; j < origPlayer.getSpellsCastThisTurn(); j++) newPlayer.addSpellCastThisTurn(); - for (int j = 0; j < origPlayer.getLandsPlayedThisTurn(); j++) - newPlayer.addLandPlayedThisTurn(); + newPlayer.setLandsPlayedThisTurn(origPlayer.getLandsPlayedThisTurn()); newPlayer.setCounters(Maps.newHashMap(origPlayer.getCounters())); newPlayer.setLifeLostLastTurn(origPlayer.getLifeLostLastTurn()); newPlayer.setLifeLostThisTurn(origPlayer.getLifeLostThisTurn()); @@ -99,7 +101,7 @@ public class GameCopier { for (Player p : newGame.getPlayers()) { ((PlayerZoneBattlefield) p.getZone(ZoneType.Battlefield)).setTriggers(false); } - + copyGameState(newGame); for (Player p : newGame.getPlayers()) { @@ -138,20 +140,27 @@ public class GameCopier { effect.removeMapped(gameObjectMap); } + if (origPhaseHandler.getCombat() != null) { + newGame.getPhaseHandler().setCombat(new Combat(origPhaseHandler.getCombat(), gameObjectMap)); + } + newGame.getAction().checkStateEffects(true); //ensure state based effects and triggers are updated newGame.getTriggerHandler().resetActiveTriggers(); if (GameSimulator.COPY_STACK) copyStack(origGame, newGame, gameObjectMap); - if (origPhaseHandler.getCombat() != null) { - newGame.getPhaseHandler().setCombat(new Combat(origPhaseHandler.getCombat(), gameObjectMap)); - } + // TODO update thisTurnCast if (advanceToPhase != null) { - newGame.getPhaseHandler().devAdvanceToPhase(advanceToPhase); + newGame.getPhaseHandler().devAdvanceToPhase(advanceToPhase, new Runnable() { + @Override + public void run() { + GameSimulator.resolveStack(newGame, aiPlayer.getWeakestOpponent()); + } + }); } - + return newGame; } @@ -185,7 +194,8 @@ public class GameCopier { RegisteredPlayer clone = new RegisteredPlayer(p.getDeck()); LobbyPlayer lp = p.getPlayer(); if (!(lp instanceof LobbyPlayerAi)) { - lp = new LobbyPlayerAi(p.getPlayer().getName(), null); + // TODO should probably also override them if they're normal AI + lp = new LobbyPlayerAi(p.getPlayer().getName(), Sets.newHashSet(AIOption.USE_SIMULATION)); } clone.setPlayer(lp); return clone; @@ -197,6 +207,7 @@ public class GameCopier { for (Card card : origGame.getCardsIn(zone)) { addCard(newGame, zone, card); } + // TODO CardsAddedThisTurn is now messed up } gameObjectMap = new CopiedGameObjectMap(newGame); @@ -271,14 +282,17 @@ public class GameCopier { cardMap.put(c, newCard); Player zoneOwner = owner; + // everything the CreatureEvaluator checks must be set here if (zone == ZoneType.Battlefield) { // TODO: Controllers' list with timestamps should be copied. zoneOwner = playerMap.get(c.getController()); newCard.setController(zoneOwner, 0); + newCard.setCameUnderControlSinceLastUpkeep(c.cameUnderControlSinceLastUpkeep()); + newCard.setPTTable(c.getSetPTTable()); newCard.setPTCharacterDefiningTable(c.getSetPTCharacterDefiningTable()); - + newCard.setPTBoost(c.getPTBoostTable()); newCard.setDamage(c.getDamage()); @@ -290,9 +304,11 @@ public class GameCopier { newCard.setChangedCardKeywords(c.getChangedCardKeywords()); newCard.setChangedCardNames(c.getChangedCardNames()); - // TODO: Is this correct? Does it not duplicate keywords from enchantments and such? - //for (KeywordInterface kw : c.getHiddenExtrinsicKeywords()) - // newCard.addHiddenExtrinsicKeyword(kw); + for (Table.Cell> kw : c.getHiddenExtrinsicKeywordsTable().cellSet()) { + newCard.addHiddenExtrinsicKeywords(kw.getRowKey(), kw.getColumnKey(), kw.getValue()); + } + newCard.updateKeywordsCache(newCard.getCurrentState()); + if (c.isTapped()) { newCard.setTapped(true); } @@ -358,7 +374,7 @@ public class GameCopier { zoneOwner.getZone(zone).add(newCard); } } - + private static SpellAbility findSAInCard(SpellAbility sa, Card c) { String saDesc = sa.getDescription(); for (SpellAbility cardSa : c.getAllSpellAbilities()) { @@ -386,7 +402,7 @@ public class GameCopier { return find(o); } } - + public GameObject find(GameObject o) { GameObject result = cardMap.get(o); if (result != null) diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameSimulator.java b/forge-ai/src/main/java/forge/ai/simulation/GameSimulator.java index 927b315bf00..7549c1f62cf 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameSimulator.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameSimulator.java @@ -31,11 +31,11 @@ public class GameSimulator { public GameSimulator(SimulationController controller, Game origGame, Player origAiPlayer, PhaseType advanceToPhase) { this.controller = controller; copier = new GameCopier(origGame); - simGame = copier.makeCopy(advanceToPhase); + simGame = copier.makeCopy(advanceToPhase, origAiPlayer); aiPlayer = (Player) copier.find(origAiPlayer); eval = new GameStateEvaluator(); - + origLines = new ArrayList<>(); debugLines = origLines; @@ -74,6 +74,8 @@ public class GameSimulator { eval.getScoreForGameState(origGame, origAiPlayer); // Print debug info. printDiff(origLines, simLines); + // make sure it gets printed + System.out.flush(); throw new RuntimeException("Game copy error. See diff output above for details."); } eval.setDebugging(false); @@ -83,7 +85,7 @@ public class GameSimulator { this.interceptor = interceptor; ((PlayerControllerAi) aiPlayer.getController()).getAi().getSimulationPicker().setInterceptor(interceptor); } - + private void printDiff(List lines1, List lines2) { int i = 0; int j = 0; @@ -117,11 +119,11 @@ public class GameSimulator { if (debugPrint) { System.out.println(str); } - if (debugLines!=null) { + if (debugLines != null) { debugLines.add(str); } } - + private SpellAbility findSaInSimGame(SpellAbility sa) { // is already an ability from sim game if (sa.getHostCard().getGame().equals(this.simGame)) { @@ -154,7 +156,7 @@ public class GameSimulator { sa = findSaInSimGame(origSa); if (sa == null) { System.err.println("Simulation: SA not found! " + origSa); - return new Score(Integer.MIN_VALUE, Integer.MIN_VALUE); + return new Score(Integer.MIN_VALUE); } debugPrint("Found SA " + sa + " on host card " + sa.getHostCard() + " with owner:"+ sa.getHostCard().getOwner()); @@ -186,14 +188,18 @@ public class GameSimulator { final SpellAbility playingSa = sa; simGame.copyLastState(); - ComputerUtil.handlePlayingSpellAbility(aiPlayer, sa, simGame, new Runnable() { + boolean success = ComputerUtil.handlePlayingSpellAbility(aiPlayer, sa, simGame, new Runnable() { @Override public void run() { if (interceptor != null) { + interceptor.announceX(playingSa); interceptor.chooseTargets(playingSa, GameSimulator.this); } } }); + if (!success) { + return new Score(Integer.MIN_VALUE); + } } // TODO: Support multiple opponents. @@ -230,8 +236,10 @@ public class GameSimulator { return score; } - private static void resolveStack(final Game game, final Player opponent) { + public static void resolveStack(final Game game, final Player opponent) { // TODO: This needs to set an AI controller for all opponents, in case of multiplayer. + PlayerControllerAi sim = new PlayerControllerAi(game, opponent, opponent.getLobbyPlayer()); + sim.setUseSimulation(true); opponent.runWithController(new Runnable() { @Override public void run() { @@ -259,9 +267,9 @@ public class GameSimulator { // Continue until stack is empty. } } - }, new PlayerControllerAi(game, opponent, opponent.getLobbyPlayer())); + }, sim); } - + public Game getSimulatedGameState() { return simGame; } @@ -269,7 +277,7 @@ public class GameSimulator { public Score getScoreForOrigGame() { return origScore; } - + public GameCopier getGameCopier() { return copier; } diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java b/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java index e3dc9e8a64c..678ab769fce 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameStateEvaluator.java @@ -15,16 +15,16 @@ public class GameStateEvaluator { public void setDebugging(boolean debugging) { this.debugging = debugging; } - + private static void debugPrint(String s) { GameSimulator.debugPrint(s); } - + private static class CombatSimResult { public GameCopier copier; public Game gameCopy; } - private CombatSimResult simulateUpcomingCombatThisTurn(final Game evalGame) { + private CombatSimResult simulateUpcomingCombatThisTurn(final Game evalGame, final Player aiPlayer) { PhaseType phase = evalGame.getPhaseHandler().getPhase(); if (phase.isAfter(PhaseType.COMBAT_DAMAGE) || evalGame.isGameOver()) { return null; @@ -38,7 +38,12 @@ public class GameStateEvaluator { } GameCopier copier = new GameCopier(evalGame); Game gameCopy = copier.makeCopy(); - gameCopy.getPhaseHandler().devAdvanceToPhase(PhaseType.COMBAT_DAMAGE); + gameCopy.getPhaseHandler().devAdvanceToPhase(PhaseType.COMBAT_DAMAGE, new Runnable() { + @Override + public void run() { + GameSimulator.resolveStack(gameCopy, aiPlayer.getWeakestOpponent()); + } + }); CombatSimResult result = new CombatSimResult(); result.copier = copier; result.gameCopy = gameCopy; @@ -61,13 +66,13 @@ public class GameStateEvaluator { return new Score(Integer.MIN_VALUE); } - + public Score getScoreForGameState(Game game, Player aiPlayer) { if (game.isGameOver()) { return getScoreForGameOver(game, aiPlayer); } - - CombatSimResult result = simulateUpcomingCombatThisTurn(game); + + CombatSimResult result = simulateUpcomingCombatThisTurn(game, aiPlayer); if (result != null) { Player aiPlayerCopy = (Player) result.copier.find(aiPlayer); if (result.gameCopy.isGameOver()) { @@ -81,6 +86,7 @@ public class GameStateEvaluator { private Score getScoreForGameStateImpl(Game game, Player aiPlayer) { int score = 0; // TODO: more than 2 players + // TODO: try and reuse evaluateBoardPosition int myCards = 0; int theirCards = 0; for (Card c : game.getCardsIn(ZoneType.Hand)) { @@ -92,7 +98,7 @@ public class GameStateEvaluator { } debugPrint("My cards in hand: " + myCards); debugPrint("Their cards in hand: " + theirCards); - if (myCards > aiPlayer.getMaxHandSize()) { + if (!aiPlayer.isUnlimitedHandSize() && myCards > aiPlayer.getMaxHandSize()) { // Count excess cards for less. score += myCards - aiPlayer.getMaxHandSize(); myCards = aiPlayer.getMaxHandSize(); @@ -102,12 +108,10 @@ public class GameStateEvaluator { score += 2 * aiPlayer.getLife(); int opponentIndex = 1; int opponentLife = 0; - for (Player opponent : game.getPlayers()) { - if (opponent != aiPlayer) { + for (Player opponent : aiPlayer.getOpponents()) { debugPrint(" Opponent " + opponentIndex + " life: -" + opponent.getLife()); opponentLife += opponent.getLife(); opponentIndex++; - } } score -= 2* opponentLife / (game.getPlayers().size() - 1); int summonSickScore = score; @@ -138,7 +142,7 @@ public class GameStateEvaluator { debugPrint("Score = " + score); return new Score(score, summonSickScore); } - + public int evalCard(Game game, Player aiPlayer, Card c) { // TODO: These should be based on other considerations - e.g. in relation to opponents state. if (c.isCreature()) { @@ -178,12 +182,12 @@ public class GameStateEvaluator { this.value = value; this.summonSickValue = value; } - + public Score(int value, int summonSickValue) { this.value = value; this.summonSickValue = summonSickValue; } - + public boolean equals(Score other) { if (other == null) return false; diff --git a/forge-ai/src/main/java/forge/ai/simulation/Plan.java b/forge-ai/src/main/java/forge/ai/simulation/Plan.java index d89d9009641..80b50e3cde3 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/Plan.java +++ b/forge-ai/src/main/java/forge/ai/simulation/Plan.java @@ -22,7 +22,7 @@ public class Plan { this.decisions = decisions; this.finalScore = finalScore; } - + public Score getFinalScore() { return finalScore; } @@ -102,6 +102,7 @@ public class Plan { final Score initialScore; final SpellAbilityRef saRef; + Integer xMana; MultiTargetSelector.Targets targets; List choices; int[] modes; @@ -112,14 +113,14 @@ public class Plan { this.prevDecision = prevDecision; this.saRef = saRef; } - + public Decision(Score initialScore, Decision prevDecision, MultiTargetSelector.Targets targets) { this.initialScore = initialScore; this.prevDecision = prevDecision; this.saRef = null; this.targets = targets; } - + public Decision(Score initialScore, Decision prevDecision, Card choice) { this.initialScore = initialScore; this.prevDecision = prevDecision; @@ -144,7 +145,11 @@ public class Plan { if (modesStr != null) { sb.append(modesStr); } else { - sb.append(saRef.toString(showHostCard)); + String sa = saRef.toString(showHostCard); + if (xMana != null) { + sa = sa.replace("(X=0)", "(X=" + xMana + ")"); + } + sb.append(sa); } if (targets != null) { sb.append(" (targets: ").append(targets).append(")"); diff --git a/forge-ai/src/main/java/forge/ai/simulation/PossibleTargetSelector.java b/forge-ai/src/main/java/forge/ai/simulation/PossibleTargetSelector.java index 18e158e9a23..10ad14f8c3d 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/PossibleTargetSelector.java +++ b/forge-ai/src/main/java/forge/ai/simulation/PossibleTargetSelector.java @@ -167,6 +167,7 @@ public class PossibleTargetSelector { private void selectTargetsByIndexImpl(int index) { targetingSa.resetTargets(); + // TODO this currently checks from max amount to just one but it doesn't check all combinations while (targetingSa.getTargets().size() < maxTargets && index < validTargets.size()) { targetingSa.getTargets().add(validTargets.get(index++)); } diff --git a/forge-ai/src/main/java/forge/ai/simulation/SimulationController.java b/forge-ai/src/main/java/forge/ai/simulation/SimulationController.java index 0bf94982686..5c9b19ddeb3 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/SimulationController.java +++ b/forge-ai/src/main/java/forge/ai/simulation/SimulationController.java @@ -48,30 +48,30 @@ public class SimulationController { private int getRecursionDepth() { return scoreStack.size() - 1; } - + public boolean shouldRecurse() { return bestScore.value != Integer.MAX_VALUE && getRecursionDepth() < MAX_DEPTH; } - - private Plan.Decision getLastDecision() { + + public Plan.Decision getLastDecision() { if (currentStack.isEmpty()) { return null; } return currentStack.get(currentStack.size() - 1); } - + private Score getCurrentScore() { return scoreStack.get(scoreStack.size() - 1); } - + public void evaluateSpellAbility(List saList, int saIndex) { currentStack.add(new Plan.Decision(getCurrentScore(), getLastDecision(), new Plan.SpellAbilityRef(saList, saIndex))); } - + public void evaluateCardChoice(Card choice) { currentStack.add(new Plan.Decision(getCurrentScore(), getLastDecision(), choice)); } - + public void evaluateChosenModes(int[] chosenModes, String modesStr) { currentStack.add(new Plan.Decision(getCurrentScore(), getLastDecision(), chosenModes, modesStr)); } @@ -87,11 +87,11 @@ public class SimulationController { } currentStack.remove(currentStack.size() - 1); } - + public Score getBestScore() { return bestScore; } - + public Plan getBestPlan() { if (!currentStack.isEmpty()) { throw new RuntimeException("getBestPlan() expects currentStack to be empty!"); @@ -155,6 +155,7 @@ public class SimulationController { } merged.modes = modes; merged.modesStr = modesStr; + merged.xMana = d.xMana; return merged; } diff --git a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityChoicesIterator.java b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityChoicesIterator.java index b940278d477..01431db679c 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityChoicesIterator.java +++ b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityChoicesIterator.java @@ -8,6 +8,7 @@ import java.util.NoSuchElementException; import org.apache.commons.math3.util.CombinatoricsUtils; +import forge.ai.ComputerUtilCost; import forge.ai.simulation.GameStateEvaluator.Score; import forge.game.card.Card; import forge.game.card.CardCollection; @@ -220,6 +221,16 @@ public class SpellAbilityChoicesIterator { return modes; } + public void announceX(SpellAbility sa) { + // TODO this should also iterate over all possible values + // (currently no additional complexity to keep performance reasonable) + if (sa.costHasManaX()) { + Integer x = ComputerUtilCost.getMaxXValue(sa, sa.getActivatingPlayer()); + sa.setXManaCostPaid(x); + controller.getLastDecision().xMana = x; + } + } + private static class AllowRepeatModesIterator implements Iterator { private int numChoices; private int max; diff --git a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java index 412f2bd8495..11120549c47 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java +++ b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java @@ -46,7 +46,7 @@ public class SpellAbilityPicker { public void setInterceptor(SpellAbilityChoicesIterator in) { this.interceptor = in; } - + private void print(String str) { if (printOutput) { System.out.println(str); @@ -60,7 +60,7 @@ public class SpellAbilityPicker { } print("---- choose ability (phase = " + phaseStr + ")"); } - + private List getCandidateSpellsAndAbilities() { CardCollection cards = ComputerUtilAbility.getAvailableCards(game, player); List all = ComputerUtilAbility.getSpellAbilities(cards, player); @@ -85,12 +85,12 @@ public class SpellAbilityPicker { continue; } sa.setActivatingPlayer(player); - + AiPlayDecision opinion = canPlayAndPayForSim(sa); // print(" " + opinion + ": " + sa); // PhaseHandler ph = game.getPhaseHandler(); // System.out.printf("Ai thinks '%s' of %s -> %s @ %s %s >>> \n", opinion, sa.getHostCard(), sa, Lang.getPossesive(ph.getPlayerTurn().getName()), ph.getPhase()); - + if (opinion != AiPlayDecision.WillPlay) continue; candidateSAs.set(writeIndex, sa); @@ -101,7 +101,7 @@ public class SpellAbilityPicker { } public SpellAbility chooseSpellAbilityToPlay(SimulationController controller) { - printOutput = (controller == null); + printOutput = controller == null; // Pass if top of stack is owned by me. if (!game.getStack().isEmpty() && game.getStack().peekAbility().getActivatingPlayer().equals(player)) { @@ -263,10 +263,13 @@ public class SpellAbilityPicker { return null; } } + if (decision.xMana != null) { + sa.setXManaCostPaid(decision.xMana); + } print("Planned decision " + plan.getNextDecisionIndex() + ": " + decision); return sa; } - + public Score getScoreForChosenAbility() { return bestScore; } @@ -338,7 +341,7 @@ public class SpellAbilityPicker { return AiPlayDecision.CantPlaySa; } - // Note: Can'tjust check condition on the top ability, because it may have + // Note: Can't just check condition on the top ability, because it may have // sub-abilities without conditions (e.g. wild slash's main ability has a // main ability with conditions but the burn sub-ability has none). if (!atLeastOneConditionMet(sa)) { @@ -394,7 +397,7 @@ public class SpellAbilityPicker { } return null; } - + private Card getPlannedChoice(CardCollection fetchList) { // TODO: Make the below more robust? if (plan != null && plan.getSelectedDecision() != null) { diff --git a/forge-core/src/main/java/forge/card/CardChangedType.java b/forge-core/src/main/java/forge/card/CardChangedType.java index 6e855548598..003e41cc47c 100644 --- a/forge-core/src/main/java/forge/card/CardChangedType.java +++ b/forge-core/src/main/java/forge/card/CardChangedType.java @@ -29,6 +29,7 @@ public class CardChangedType { // takes care of individual card types private final CardType addType; private final CardType removeType; + private final boolean addAllCreatureTypes; private final boolean removeSuperTypes; private final boolean removeCardTypes; private final boolean removeSubTypes; @@ -37,12 +38,12 @@ public class CardChangedType { private final boolean removeArtifactTypes; private final boolean removeEnchantmentTypes; - public CardChangedType(final CardType addType0, final CardType removeType0, final boolean removeSuperType0, - final boolean removeCardType0, final boolean removeSubType0, final boolean removeLandType0, - final boolean removeCreatureType0, final boolean removeArtifactType0, - final boolean removeEnchantmentTypes0) { + public CardChangedType(final CardType addType0, final CardType removeType0, final boolean addAllCreatureTypes0, + final boolean removeSuperType0, final boolean removeCardType0, final boolean removeSubType0, + final boolean removeLandType0, final boolean removeCreatureType0, final boolean removeArtifactType0, final boolean removeEnchantmentTypes0) { addType = addType0; removeType = removeType0; + addAllCreatureTypes = addAllCreatureTypes0; removeSuperTypes = removeSuperType0; removeCardTypes = removeCardType0; removeSubTypes = removeSubType0; @@ -60,6 +61,10 @@ public class CardChangedType { return removeType; } + public final boolean isAddAllCreatureTypes() { + return addAllCreatureTypes; + } + public final boolean isRemoveSuperTypes() { return removeSuperTypes; } diff --git a/forge-core/src/main/java/forge/card/CardType.java b/forge-core/src/main/java/forge/card/CardType.java index 0a332ac2371..8dd5661b28c 100644 --- a/forge-core/src/main/java/forge/card/CardType.java +++ b/forge-core/src/main/java/forge/card/CardType.java @@ -51,8 +51,6 @@ public final class CardType implements Comparable, CardTypeView { public static final CardTypeView EMPTY = new CardType(false); - public static final String AllCreatureTypes = "AllCreatureTypes"; - public enum CoreType { Artifact(true, "artifacts"), Conspiracy(false, "conspiracies"), @@ -113,6 +111,9 @@ public final class CardType implements Comparable, CardTypeView { private final Set coreTypes = EnumSet.noneOf(CoreType.class); private final Set supertypes = EnumSet.noneOf(Supertype.class); private final Set subtypes = Sets.newLinkedHashSet(); + private boolean allCreatureTypes = false; + private final Set excludedCreatureSubtypes = Sets.newLinkedHashSet(); + private boolean incomplete = false; private transient String calculatedType = null; @@ -125,6 +126,8 @@ public final class CardType implements Comparable, CardTypeView { } public CardType(final CardType from0) { addAll(from0); + allCreatureTypes = from0.allCreatureTypes; + excludedCreatureSubtypes.addAll(from0.excludedCreatureSubtypes); } public CardType(final CardTypeView from0) { addAll(from0); @@ -153,6 +156,9 @@ public final class CardType implements Comparable, CardTypeView { return false; } public boolean addAll(final Iterable types) { + if (types == null) { + return false; + } boolean changed = false; for (final String t : types) { if (add(t)) { @@ -235,16 +241,17 @@ public final class CardType implements Comparable, CardTypeView { } boolean changed = Iterables.removeIf(subtypes, Predicates.IS_CREATURE_TYPE); // need to remove AllCreatureTypes too when setting Creature Type - if (subtypes.remove(AllCreatureTypes)) { + if (allCreatureTypes) { changed = true; } + allCreatureTypes = false; subtypes.addAll(ctypes); return changed; } @Override public boolean isEmpty() { - return coreTypes.isEmpty() && supertypes.isEmpty() && subtypes.isEmpty(); + return coreTypes.isEmpty() && supertypes.isEmpty() && subtypes.isEmpty() && !excludedCreatureSubtypes.isEmpty(); } @Override @@ -259,18 +266,29 @@ public final class CardType implements Comparable, CardTypeView { public Iterable getSubtypes() { return subtypes; } + + @Override + public Iterable getExcludedCreatureSubTypes() { + return excludedCreatureSubtypes; + } + @Override public Set getCreatureTypes() { final Set creatureTypes = Sets.newHashSet(); - if (isCreature() || isTribal()) { - for (final String t : subtypes) { - if (isACreatureType(t) || t.equals(AllCreatureTypes)) { - creatureTypes.add(t); - } + if (!isCreature() && !isTribal()) { + return creatureTypes; + } + if (hasAllCreatureTypes()) { // it should return list of all creature types + creatureTypes.addAll(getAllCreatureTypes()); + creatureTypes.removeAll(this.excludedCreatureSubtypes); + } else { + for (final String t : Iterables.filter(subtypes, Predicates.IS_CREATURE_TYPE)) { + creatureTypes.add(t); } } return creatureTypes; } + @Override public Set getLandTypes() { final Set landTypes = Sets.newHashSet(); @@ -304,17 +322,26 @@ public final class CardType implements Comparable, CardTypeView { } return false; } + @Override public boolean hasType(final CoreType type) { return coreTypes.contains(type); } + @Override public boolean hasSupertype(final Supertype supertype) { return supertypes.contains(supertype); } + + @Override + public boolean hasAllCreatureTypes() { + if (!isCreature() && !isTribal()) { return false; } + return this.allCreatureTypes; + } + @Override public boolean hasSubtype(final String subtype) { - if (isACreatureType(subtype) && subtypes.contains(AllCreatureTypes)) { + if (hasCreatureType(subtype)) { return true; } return subtypes.contains(subtype); @@ -327,7 +354,13 @@ public final class CardType implements Comparable, CardTypeView { creatureType = toMixedCase(creatureType); if (!isACreatureType(creatureType)) { return false; } - return subtypes.contains(creatureType) || subtypes.contains(AllCreatureTypes); + if (excludedCreatureSubtypes.contains(creatureType)) { + return false; + } + if (allCreatureTypes) { + return true; + } + return subtypes.contains(creatureType); } private static String toMixedCase(final String s) { if (s.isEmpty()) { @@ -449,11 +482,25 @@ public final class CardType implements Comparable, CardTypeView { @Override public String toString() { if (calculatedType == null) { - if (subtypes.isEmpty()) { - calculatedType = StringUtils.join(getTypesBeforeDash(), ' '); - } else { - calculatedType = StringUtils.join(getTypesBeforeDash(), ' ') + " - " + StringUtils.join(subtypes, " "); + StringBuilder sb = new StringBuilder(StringUtils.join(getTypesBeforeDash(), ' ')); + if (!subtypes.isEmpty() || hasAllCreatureTypes()) { + sb.append(" - "); } + if (!subtypes.isEmpty()) { + sb.append(StringUtils.join(subtypes, " ")); + } + if (hasAllCreatureTypes()) { + if (!subtypes.isEmpty()) { + sb.append(" "); + } + sb.append("(All"); + if (!excludedCreatureSubtypes.isEmpty()) { + sb.append(" except ").append(StringUtils.join(excludedCreatureSubtypes, " ")); + } + sb.append(")"); + } + + calculatedType = sb.toString(); } return calculatedType; } @@ -496,7 +543,7 @@ public final class CardType implements Comparable, CardTypeView { if (ct.isRemoveCreatureTypes()) { Iterables.removeIf(newType.subtypes, Predicates.IS_CREATURE_TYPE); // need to remove AllCreatureTypes too when removing creature Types - newType.subtypes.remove(AllCreatureTypes); + newType.allCreatureTypes = false; } if (ct.isRemoveArtifactTypes()) { Iterables.removeIf(newType.subtypes, Predicates.IS_ARTIFACT_TYPE); @@ -510,6 +557,16 @@ public final class CardType implements Comparable, CardTypeView { } if (ct.getAddType() != null) { newType.addAll(ct.getAddType()); + if (ct.getAddType().hasAllCreatureTypes()) { + newType.allCreatureTypes = true; + } + } + if (ct.isAddAllCreatureTypes()) { + newType.allCreatureTypes = true; + } + // remove specific creature types from all creature types + if (ct.getRemoveType() != null && newType.allCreatureTypes) { + newType.excludedCreatureSubtypes.addAll(Lists.newArrayList(Iterables.filter(ct.getRemoveType(), Predicates.IS_CREATURE_TYPE))); } } // sanisfy subtypes @@ -524,9 +581,14 @@ public final class CardType implements Comparable, CardTypeView { if (this.incomplete) { return; } + if (!isCreature() && !isTribal()) { + allCreatureTypes = false; + } + if (subtypes.isEmpty()) { + return; + } if (!isCreature() && !isTribal()) { Iterables.removeIf(subtypes, Predicates.IS_CREATURE_TYPE); - subtypes.remove(AllCreatureTypes); } if (!isLand()) { Iterables.removeIf(subtypes, Predicates.IS_LAND_TYPE); @@ -583,9 +645,21 @@ public final class CardType implements Comparable, CardTypeView { if (ctOther == null) { return false; } - if (this.subtypes.contains(AllCreatureTypes) && ctOther.hasSubtype(AllCreatureTypes)) { - return true; + if (!isCreature() && !isTribal()) { + return false; } + if (!ctOther.isCreature() && !ctOther.isTribal()) { + return false; + } + + // special cases for if any of them is all creature types + if (this.allCreatureTypes && ctOther.hasAllCreatureTypes()) { + // no type is exluded so they should share all creature types + if (excludedCreatureSubtypes.isEmpty() && Iterables.isEmpty(ctOther.getExcludedCreatureSubTypes())) { + return true; + } + } + for (final String type : getCreatureTypes()) { if (ctOther.hasCreatureType(type)) { return true; @@ -642,6 +716,9 @@ public final class CardType implements Comparable, CardTypeView { if (ctOther == null) { return false; } + if (sharesCreaturetypeWith(ctOther)) { + return true; + } for (final String t : ctOther.getSubtypes()) { if (hasSubtype(t)) { return true; @@ -722,7 +799,12 @@ public final class CardType implements Comparable, CardTypeView { return CardType.isALandType(input); } }; - + public static Predicate IS_BASIC_LAND_TYPE = new Predicate() { + @Override + public boolean apply(String input) { + return CardType.isABasicLandType(input); + } + }; public static Predicate IS_ARTIFACT_TYPE = new Predicate() { @Override public boolean apply(String input) { diff --git a/forge-core/src/main/java/forge/card/CardTypeView.java b/forge-core/src/main/java/forge/card/CardTypeView.java index f89452baac8..4c27266e72a 100644 --- a/forge-core/src/main/java/forge/card/CardTypeView.java +++ b/forge-core/src/main/java/forge/card/CardTypeView.java @@ -12,13 +12,18 @@ public interface CardTypeView extends Iterable, Serializable { Iterable getCoreTypes(); Iterable getSupertypes(); Iterable getSubtypes(); + Iterable getExcludedCreatureSubTypes(); + Set getCreatureTypes(); Set getLandTypes(); + + boolean hasStringType(String t); boolean hasType(CoreType type); boolean hasSupertype(Supertype supertype); boolean hasSubtype(String subtype); boolean hasCreatureType(String creatureType); + boolean hasAllCreatureTypes(); public boolean sharesCreaturetypeWith(final CardTypeView ctOther); public boolean sharesLandTypeWith(final CardTypeView ctOther); diff --git a/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java b/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java index 0aa65acf1c3..7eb4291f684 100644 --- a/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java +++ b/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java @@ -92,7 +92,6 @@ public abstract class DeckGeneratorBase { final Iterable cards = selectCardsOfMatchingColorForPlayer(forAi); // build subsets based on type - final Iterable creatures = Iterables.filter(cards, Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard.FN_GET_RULES)); final int creatCnt = (int) Math.ceil(getCreaturePercentage() * size); trace.append("Creatures to add:").append(creatCnt).append("\n"); diff --git a/forge-core/src/main/java/forge/util/lang/LangGerman.java b/forge-core/src/main/java/forge/util/lang/LangGerman.java index 3c9d6dc1674..30558194d07 100644 --- a/forge-core/src/main/java/forge/util/lang/LangGerman.java +++ b/forge-core/src/main/java/forge/util/lang/LangGerman.java @@ -26,7 +26,6 @@ public class LangGerman extends Lang { return getPossesive(owner) + " " + object; } - @Override public String getNickName(final String name) { if (name.contains(",")) { diff --git a/forge-game/src/main/java/forge/game/ForgeScript.java b/forge-game/src/main/java/forge/game/ForgeScript.java index 4dbb76d9e7e..6183d6f2294 100644 --- a/forge-game/src/main/java/forge/game/ForgeScript.java +++ b/forge-game/src/main/java/forge/game/ForgeScript.java @@ -156,6 +156,8 @@ public class ForgeScript { return sa.isKicked(); } else if (property.equals("Loyalty")) { return sa.isPwAbility(); + } else if (property.equals("nonLoyalty")) { + return !sa.isPwAbility(); } else if (property.equals("Aftermath")) { return sa.isAftermath(); } else if (property.equals("MorphUp")) { diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index f158cfcb9be..56a06649083 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -355,7 +355,7 @@ public class GameAction { ReplacementResult repres = game.getReplacementHandler().run(ReplacementType.Moved, repParams); if (repres != ReplacementResult.NotReplaced) { // reset failed manifested Cards back to original - if (c.isManifested() && !c.isInZone(ZoneType.Battlefield)) { + if (c.isManifested() && !c.isInPlay()) { c.forceTurnFaceUp(); } @@ -373,7 +373,7 @@ public class GameAction { } // was replaced with another Zone Change - if (toBattlefield && !c.isInZone(ZoneType.Battlefield)) { + if (toBattlefield && !c.isInPlay()) { if (c.removeChangedState()) { c.updateStateForView(); } @@ -1171,7 +1171,7 @@ public class GameAction { } if (c.isCreature() && c.isPaired()) { Card partner = c.getPairedWith(); - if (!partner.isCreature() || c.getController() != partner.getController() || !c.isInZone(ZoneType.Battlefield)) { + if (!partner.isCreature() || c.getController() != partner.getController() || !c.isInPlay()) { c.setPairedWith(null); partner.setPairedWith(null); affectedCards.add(c); diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index b3fecdba818..96a974d2179 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -96,7 +96,7 @@ public final class GameActionUtil { Card source = sa.getHostCard(); final Game game = source.getGame(); - if (sa.isSpell() && !source.isInZone(ZoneType.Battlefield)) { + if (sa.isSpell() && !source.isInPlay()) { boolean lkicheck = false; Card newHost = ((Spell)sa).getAlternateHost(source); diff --git a/forge-game/src/main/java/forge/game/GlobalRuleChange.java b/forge-game/src/main/java/forge/game/GlobalRuleChange.java index d0381166b4b..2a02d696449 100644 --- a/forge-game/src/main/java/forge/game/GlobalRuleChange.java +++ b/forge-game/src/main/java/forge/game/GlobalRuleChange.java @@ -25,7 +25,6 @@ public enum GlobalRuleChange { alwaysWither ("All damage is dealt as though its source had wither."), attackerChoosesBlockers ("The attacking player chooses how each creature blocks each combat."), manaBurn ("A player losing unspent mana causes that player to lose that much life."), - manapoolsDontEmpty ("Mana pools don't empty as steps and phases end."), noCreatureETBTriggers ("Creatures entering the battlefield don't cause abilities to trigger."), noCreatureDyingTriggers ("Creatures dying don't cause abilities to trigger."), noLegendRule ("The legend rule doesn't apply."), diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 603c4cc99a0..a8bda73a098 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1689,10 +1689,6 @@ public class AbilityUtils { // accept straight numbers if (l[0].startsWith("Number$")) { final String number = l[0].substring(7); - if (number.equals("ChosenNumber")) { // TODO remove in favor of Count ChosenNumber - int x = c.getChosenNumber() == null ? 0 : c.getChosenNumber(); - return doXMath(x, expr, c, ctb); - } return doXMath(Integer.parseInt(number), expr, c, ctb); } @@ -2471,11 +2467,11 @@ public class AbilityUtils { // Figure out how to count each class separately. for (Card card : adventurers) { + // cards with all creature types will just return full list Set creatureTypes = card.getType().getCreatureTypes(); - boolean anyType = creatureTypes.contains(CardType.AllCreatureTypes); creatureTypes.retainAll(partyTypes); - if (anyType || creatureTypes.size() == 4) { + if (creatureTypes.size() == 4) { wildcard.add(card); if (wildcard.size() >= 4) { @@ -2574,8 +2570,7 @@ public class AbilityUtils { Iterables.addAll(creatTypes, card.getType().getCreatureTypes()); } // filter out fun types? - int n = creatTypes.contains(CardType.AllCreatureTypes) ? CardType.getAllCreatureTypes().size() : creatTypes.size(); - return doXMath(n, expr, c, ctb); + return doXMath(creatTypes.size(), expr, c, ctb); } // Count$Chroma. @@ -2882,8 +2877,7 @@ public class AbilityUtils { for (Card card : cards) { Iterables.addAll(creatTypes, card.getType().getCreatureTypes()); } - int n = creatTypes.contains(CardType.AllCreatureTypes) ? CardType.getAllCreatureTypes().size() : creatTypes.size(); - return doXMath(n, expr, c, ctb); + return doXMath(creatTypes.size(), expr, c, ctb); } // Complex counting methods CardCollectionView someCards = getCardListForXCount(c, player, sq, ctb); diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index f0c98e4b62b..bd7cfb2ada7 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -135,9 +135,9 @@ public abstract class SpellAbilityEffect { } } - String currentName = (sa.getHostCard().getName()); - String substitutedDesc = TextUtil.fastReplace(sb.toString(), "CARDNAME", CardTranslation.getTranslatedName(currentName)); - substitutedDesc = TextUtil.fastReplace(substitutedDesc, "NICKNAME", Lang.getInstance().getNickName(CardTranslation.getTranslatedName(currentName))); + String currentName = CardTranslation.getTranslatedName(sa.getHostCard().getName()); + String substitutedDesc = TextUtil.fastReplace(sb.toString(), "CARDNAME", currentName); + substitutedDesc = TextUtil.fastReplace(substitutedDesc, "NICKNAME", Lang.getInstance().getNickName(currentName)); return substitutedDesc; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/AddPhaseEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AddPhaseEffect.java index 6f7c310e910..3ec8a944860 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AddPhaseEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AddPhaseEffect.java @@ -49,7 +49,7 @@ public class AddPhaseEffect extends SpellAbilityEffect { extraPhaseList.addAll(PhaseType.PHASE_GROUPS.get(0)); } else if (extra.equals("Combat")) { extraPhaseList.addAll(PhaseType.PHASE_GROUPS.get(2)); - } else { // Currently no effect will add End Phase + } else { // Currently no effect will add End Phase extraPhaseList.add(PhaseType.smartValueOf(extra)); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java index 853e2b616e3..0616ed3e244 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffectBase.java @@ -50,6 +50,7 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { final Card source = sa.getHostCard(); final Game game = source.getGame(); + boolean addAllCreatureTypes = false; boolean removeSuperTypes = false; boolean removeCardTypes = false; boolean removeSubTypes = false; @@ -60,6 +61,10 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { boolean removeAll = sa.hasParam("RemoveAllAbilities"); + if (sa.hasParam("AddAllCreatureTypes")) { + addAllCreatureTypes = true; + } + if (sa.hasParam("RemoveSuperTypes")) { removeSuperTypes = true; } @@ -93,8 +98,9 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect { c.addNewPT(power, toughness, timestamp, 0); } - if (!addType.isEmpty() || !removeType.isEmpty() || removeCreatureTypes) { - c.addChangedCardTypes(addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes, + if (!addType.isEmpty() || !removeType.isEmpty() || addAllCreatureTypes || removeSuperTypes + || removeCardTypes || removeSubTypes || removeLandTypes || removeCreatureTypes || removeArtifactTypes || removeEnchantmentTypes) { + c.addChangedCardTypes(addType, removeType, addAllCreatureTypes, removeSuperTypes, removeCardTypes, removeSubTypes, removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes, timestamp, 0, true, false); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/BondEffect.java b/forge-game/src/main/java/forge/game/ability/effects/BondEffect.java index 7a05d732a38..32814c577d3 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/BondEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/BondEffect.java @@ -17,7 +17,7 @@ public class BondEffect extends SpellAbilityEffect { CardCollectionView trigCards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa); // Check that this card hasn't already become paired by an earlier trigger - if (trigCards.getFirst().isPaired() || !trigCards.getFirst().isInZone(ZoneType.Battlefield)) { + if (trigCards.getFirst().isPaired() || !trigCards.getFirst().isInPlay()) { return; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeTextEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeTextEffect.java index d7174ab3bac..115b7bab66d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeTextEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeTextEffect.java @@ -70,7 +70,7 @@ public class ChangeTextEffect extends SpellAbilityEffect { kindOfType = "basic land"; } else if (changedTypeWordsArray[0].equals("ChooseCreatureType")) { validTypes.addAll(CardType.Constant.CREATURE_TYPES); - kindOfType = "creature"; + kindOfType = "Creature"; } changedTypeWordOriginal = sa.getActivatingPlayer().getController().chooseSomeType(kindOfType, sa, validTypes, Lists.newArrayList()); } else { @@ -86,7 +86,7 @@ public class ChangeTextEffect extends SpellAbilityEffect { kindOfType = "basic land"; } else if (changedTypeWordsArray[1].equals("ChooseCreatureType")) { validTypes.addAll(CardType.Constant.CREATURE_TYPES); - kindOfType = "creature"; + kindOfType = "Creature"; } changedTypeWordNew = sa.getActivatingPlayer().getController().chooseSomeType(kindOfType, sa, validTypes, forbiddenTypes); } else { @@ -102,7 +102,7 @@ public class ChangeTextEffect extends SpellAbilityEffect { if (changedColorWordOriginal != null && changedColorWordNew != null) { c.addChangedTextColorWord(changedColorWordOriginal, changedColorWordNew, timestamp, 0); } - if (changedTypeWordOriginal != null && changedTypeWordNew != null ) { + if (changedTypeWordOriginal != null && changedTypeWordNew != null) { c.addChangedTextTypeWord(changedTypeWordOriginal, changedTypeWordNew, timestamp, 0); } @@ -123,6 +123,8 @@ public class ChangeTextEffect extends SpellAbilityEffect { } game.fireEvent(new GameEventCardStatsChanged(c)); + c.updateStateForView(); + c.updateTypesForView(); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index 99ec1d54876..31fd27cb327 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -272,8 +272,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { sb.append("."); } else if (origin.equals("Battlefield")) { // TODO Expand on this Description as more cards use it - // for the non-targeted SAs when you choose what is returned on - // resolution + // for the non-targeted SAs when you choose what is returned on resolution sb.append("Return ").append(num).append(" ").append(type).append(" card(s) "); sb.append(" to your ").append(destination); } @@ -361,8 +360,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { sb.append(fromGraveyard); } - // this needs to be zero indexed. Top = 0, Third = 2, -1 = - // Bottom + // this needs to be zero indexed. Top = 0, Third = 2, -1 = Bottom final int libraryPosition = sa.hasParam("LibraryPosition") ? AbilityUtils.calculateAmount(host, sa.getParam("LibraryPosition"), sa) : 0; if (libraryPosition == -1) { @@ -451,9 +449,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect { sb.append(sa.getParam("AlternativeDestinationMessage")); Player alterDecider = player; if (sa.hasParam("AlternativeDecider")) { - alterDecider = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("AlternativeDecider"), sa).get(0); + PlayerCollection deciders = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("AlternativeDecider"), sa); + alterDecider = deciders.isEmpty() ? null : deciders.get(0); } - if (!alterDecider.getController().confirmAction(sa, PlayerActionConfirmMode.ChangeZoneToAltDestination, sb.toString())) { + if (alterDecider != null && !alterDecider.getController().confirmAction(sa, PlayerActionConfirmMode.ChangeZoneToAltDestination, sb.toString())) { destination = ZoneType.smartValueOf(sa.getParam("DestinationAlternative")); altDest = true; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java index ec348aebae2..988e313275a 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java @@ -33,17 +33,18 @@ public class CharmEffect extends SpellAbilityEffect { } } - int indx = 0; List choices = Lists.newArrayList(sa.getAdditionalAbilityList("Choices")); - if (restriction != null) { - List toRemove = Lists.newArrayList(); - for (AbilitySub ch : choices) { - if (restriction.contains(ch.getDescription())) { - toRemove.add(ch); - } + List toRemove = Lists.newArrayList(); + for (AbilitySub ch : choices) { + // 603.3c If one of the modes would be illegal, that mode can't be chosen. + if ((ch.usesTargeting() && ch.isTrigger() && ch.getTargetRestrictions().getNumCandidates(ch, true) == 0) || + (restriction != null && restriction.contains(ch.getDescription()))) { + toRemove.add(ch); } - choices.removeAll(toRemove); } + choices.removeAll(toRemove); + + int indx = 0; // set CharmOrder for (AbilitySub sub : choices) { sub.setSVar("CharmOrder", Integer.toString(indx)); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java index a7f8585bea9..a328e38b68b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java @@ -127,7 +127,7 @@ public class ControlGainEffect extends SpellAbilityEffect { } // check for lose control criteria right away - if (lose != null && lose.contains("LeavesPlay") && !source.isInZone(ZoneType.Battlefield)) { + if (lose != null && lose.contains("LeavesPlay") && !source.isInPlay()) { return; } if (lose != null && lose.contains("Untap") && !source.isTapped()) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/DeclareCombatantsEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DeclareCombatantsEffect.java index a7c7c5ba6d6..f7d5b928985 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DeclareCombatantsEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DeclareCombatantsEffect.java @@ -32,18 +32,18 @@ public class DeclareCombatantsEffect extends SpellAbilityEffect { @Override public void resolve(SpellAbility sa) { List tgtPlayers = getDefinedPlayersOrTargeted(sa); - + final boolean attackers = sa.hasParam("DeclareAttackers"); final boolean blockers = sa.hasParam("DeclareBlockers"); - + String until = sa.getParam("Until"); boolean untilEoT = "EndOfTurn".equals(until); - + for (Player p : tgtPlayers) { // Obviously the last player will be applied final PhaseHandler ph = p.getGame().getPhaseHandler(); if (attackers) ph.setPlayerDeclaresAttackers(p); if (blockers) ph.setPlayerDeclaresBlockers(p); - + GameCommand removeOverrides = new GameCommand() { private static final long serialVersionUID = -8064627517852651016L; @@ -53,7 +53,7 @@ public class DeclareCombatantsEffect extends SpellAbilityEffect { if (blockers) ph.setPlayerDeclaresBlockers(null); } }; - + if (untilEoT) p.getGame().getEndOfTurn().addUntil(removeOverrides); else diff --git a/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java index 8c47f586c53..9adec6a686e 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java @@ -56,11 +56,7 @@ public class DelayedTriggerEffect extends SpellAbilityEffect { if (sa.hasParam("RememberObjects")) { for (final String rem : sa.getParam("RememberObjects").split(",")) { - for (final Object o : AbilityUtils.getDefinedObjects(sa.getHostCard(), rem, sa)) { - if (o instanceof SpellAbility) { - // "RememberObjects$ Remembered" don't remember spellability - continue; - } + for (final Object o : AbilityUtils.getDefinedEntities(sa.getHostCard(), rem, sa)) { delTrig.addRemembered(o); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java index fe82dc1738c..1fb6c9616a3 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java @@ -81,7 +81,7 @@ public class EffectEffect extends SpellAbilityEffect { if (sa.hasParam("RememberObjects")) { rememberList = new FCollection<>(); for (final String rem : sa.getParam("RememberObjects").split(",")) { - rememberList.addAll(AbilityUtils.getDefinedObjects(hostCard, rem, sa)); + rememberList.addAll(AbilityUtils.getDefinedEntities(hostCard, rem, sa)); } if (sa.hasParam("ForgetCounter")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java index cee5d82d45a..d2410394a6a 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java @@ -28,7 +28,6 @@ public class ImmediateTriggerEffect extends SpellAbilityEffect { } return ""; - } @Override @@ -60,11 +59,7 @@ public class ImmediateTriggerEffect extends SpellAbilityEffect { if (sa.hasParam("RememberObjects")) { for (final String rem : sa.getParam("RememberObjects").split(",")) { - for (final Object o : AbilityUtils.getDefinedObjects(sa.getHostCard(), rem, sa)) { - if (o instanceof SpellAbility) { - // "RememberObjects$ Remembered" don't remember spellability - continue; - } + for (final Object o : AbilityUtils.getDefinedEntities(sa.getHostCard(), rem, sa)) { immediateTrig.addRemembered(o); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java index 44d33726de5..8839022cb69 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpAllEffect.java @@ -17,9 +17,9 @@ import forge.game.event.GameEventCardStatsChanged; import forge.game.player.PlayerCollection; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; -import forge.util.TextUtil; public class PumpAllEffect extends SpellAbilityEffect { + private static void applyPumpAll(final SpellAbility sa, final Iterable list, final int a, final int d, final List keywords, final List affectedZones) { @@ -110,7 +110,7 @@ public class PumpAllEffect extends SpellAbilityEffect { String desc = ""; if (sa.hasParam("SpellDescription")) { - desc = TextUtil.fastReplace(sa.getParam("SpellDescription"), "CARDNAME", sa.getHostCard().getName()); + desc = sa.getParam("SpellDescription"); } sb.append(desc); diff --git a/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java index 2c949fa94dd..da7d6c479e5 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java @@ -16,7 +16,6 @@ import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerHandler; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; -import forge.util.TextUtil; import forge.util.collect.FCollectionView; public class RestartGameEffect extends SpellAbilityEffect { @@ -110,6 +109,6 @@ public class RestartGameEffect extends SpellAbilityEffect { desc = "Restart the game."; } - return TextUtil.fastReplace(desc, "CARDNAME", sa.getHostCard().getName()); + return desc; } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/SetStateEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SetStateEffect.java index a251d86ca6f..c1ee740946f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SetStateEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SetStateEffect.java @@ -87,12 +87,12 @@ public class SetStateEffect extends SpellAbilityEffect { // Cards which are not on the battlefield should not be able to transform. // TurnFace should be allowed in other zones like Exile too - if (!"TurnFace".equals(mode) && !gameCard.isInZone(ZoneType.Battlefield) && !sa.hasParam("ETB")) { + if (!"TurnFace".equals(mode) && !gameCard.isInPlay() && !sa.hasParam("ETB")) { continue; } // facedown cards that are not Permanent, can't turn faceup there - if ("TurnFace".equals(mode) && gameCard.isFaceDown() && gameCard.isInZone(ZoneType.Battlefield)) { + if ("TurnFace".equals(mode) && gameCard.isFaceDown() && gameCard.isInPlay()) { if (gameCard.hasMergedCard()) { boolean hasNonPermanent = false; Card nonPermanentCard = null; @@ -119,7 +119,7 @@ public class SetStateEffect extends SpellAbilityEffect { } // Merged faceup permanent that have double faced cards can't turn face down - if ("TurnFace".equals(mode) && !gameCard.isFaceDown() && gameCard.isInZone(ZoneType.Battlefield) + if ("TurnFace".equals(mode) && !gameCard.isFaceDown() && gameCard.isInPlay() && gameCard.hasMergedCard()) { boolean hasBackSide = false; for (final Card c : gameCard.getMergedCards()) { diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index be2815f6001..cc9b8b24bbe 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1478,7 +1478,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { long timestamp = game.getNextTimestamp(); counterTypeTimestamps.put(counterType, timestamp); // becomes land in instead of other card types - addChangedCardTypes(new CardType(ImmutableList.of("Land"), false), null, false, true, true, false, false, false, false, timestamp, 0, updateView, false); + addChangedCardTypes(new CardType(ImmutableList.of("Land"), false), null, false, false, true, true, false, false, false, false, timestamp, 0, updateView, false); String abStr = "AB$ ManaReflected | Cost$ T | Valid$ Defined.Self | ColorOrType$ Color | ReflectProperty$ Is | SpellDescription$ Add one mana of any of this card's colors."; @@ -2408,7 +2408,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } // CantBlockBy static abilities - if (game != null && isCreature() && isInZone(ZoneType.Battlefield)) { + if (game != null && isCreature() && isInPlay()) { for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { if (equals(ca)) { continue; @@ -2453,7 +2453,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { sb.append(linebreak); // Currently the maximum levels of all Class cards are all 3 for (int level = 1; level <= 3; ++level) { - boolean disabled = level > getClassLevel() && isInZone(ZoneType.Battlefield); + boolean disabled = level > getClassLevel() && isInPlay(); // Class second part is a static ability that grants the other abilities for (final StaticAbility st : state.getStaticAbilities()) { if (st.isClassLevelNAbility(level) && !st.isSecondary()) { @@ -2880,7 +2880,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // add Facedown abilities from Original state but only if this state is face down // need CardStateView#getState or might crash in StackOverflow - if (isInZone(ZoneType.Battlefield)) { + if (isInPlay()) { if ((null == mana || false == mana) && isFaceDown() && state.getView().getState() == CardStateName.FaceDown) { for (SpellAbility sa : getState(CardStateName.Original).getNonManaAbilities()) { if (sa.isManifestUp() || sa.isMorphUp()) { @@ -3009,7 +3009,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // is this "Card" supposed to be a token? public final boolean isToken() { - if (isInZone(ZoneType.Battlefield) && hasMergedCard()) { + if (isInPlay() && hasMergedCard()) { return getTopMergedCard().token; } return token; @@ -3027,7 +3027,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public final boolean isTokenCard() { - if (isInZone(ZoneType.Battlefield) && hasMergedCard()) { + if (isInPlay() && hasMergedCard()) { return getTopMergedCard().tokenCard; } return tokenCard; @@ -3533,12 +3533,13 @@ public class Card extends GameEntity implements Comparable, IHasSVars { return getType(currentState); } public final CardTypeView getType(CardState state) { - if (changedCardTypes.isEmpty() && changedCardTypesCharacterDefining.isEmpty()) { + final Iterable changedCardTypes = getChangedCardTypes(); + if (Iterables.isEmpty(changedCardTypes)) { return state.getType(); } // CR 506.4 attacked planeswalkers leave combat boolean checkCombat = state.getType().isPlaneswalker() && game.getCombat() != null && !game.getCombat().getAttackersOf(this).isEmpty(); - CardTypeView types = state.getType().getTypeWithChanges(getChangedCardTypes()); + CardTypeView types = state.getType().getTypeWithChanges(changedCardTypes); if (checkCombat && !types.isPlaneswalker()) { game.getCombat().removeFromCombat(this); } @@ -3548,14 +3549,12 @@ public class Card extends GameEntity implements Comparable, IHasSVars { public final CardTypeView getOriginalType() { return getOriginalType(currentState); } - public final CardTypeView getOriginalType(CardState state) { return state.getType(); } // TODO add changed type by card text public Iterable getChangedCardTypes() { - Iterable byText = changedTypeByText == null ? ImmutableList.of() : ImmutableList.of(this.changedTypeByText); return Iterables.unmodifiableIterable(Iterables.concat( @@ -3563,7 +3562,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { byText, // Layer 3 by Word Changes, changedCardTypesCharacterDefining.values(), // Layer 4 changedCardTypes.values() // Layer 6 - )); + )); } public Table getChangedCardTypesTable() { @@ -3618,7 +3617,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public Iterable getChangedCardKeywordsList() { - return Iterables.concat( changedCardKeywordsByText.values(), // Layer 3 ImmutableList.of(new KeywordsChange(ImmutableList.of(), null, this.hasRemoveIntrinsic())), // Layer 4 @@ -3630,7 +3628,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { return changedCardKeywords; } - public Table getChangedCardColorsTable() { return changedCardColors; } @@ -3646,7 +3643,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public final void addChangedCardTypesByText(final CardType addType, final long timestamp, final long staticId, final boolean updateView) { - changedCardTypesByText.put(timestamp, staticId, new CardChangedType(addType, null, true, true, true, false, false, false, false)); + changedCardTypesByText.put(timestamp, staticId, new CardChangedType(addType, null, false, true, true, true, false, false, false, false)); // setting card type via text, does overwrite any other word change effects? this.changedTextColors.addEmpty(timestamp, staticId); @@ -3657,20 +3654,20 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } } - public final void addChangedCardTypes(final CardType addType, final CardType removeType, + public final void addChangedCardTypes(final CardType addType, final CardType removeType, final boolean addAllCreatureTypes, final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes, final boolean removeLandTypes, final boolean removeCreatureTypes, final boolean removeArtifactTypes, final boolean removeEnchantmentTypes, final long timestamp, final long staticId, final boolean updateView, final boolean cda) { (cda ? changedCardTypesCharacterDefining : changedCardTypes).put(timestamp, staticId, new CardChangedType( - addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes, + addType, removeType, addAllCreatureTypes, removeSuperTypes, removeCardTypes, removeSubTypes, removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes)); if (updateView) { updateTypesForView(); } } - public final void addChangedCardTypes(final Iterable types, final Iterable removeTypes, + public final void addChangedCardTypes(final Iterable types, final Iterable removeTypes, final boolean addAllCreatureTypes, final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes, final boolean removeLandTypes, final boolean removeCreatureTypes, final boolean removeArtifactTypes, final boolean removeEnchantmentTypes, @@ -3685,7 +3682,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { removeType = new CardType(removeTypes, true); } - addChangedCardTypes(addType, removeType, removeSuperTypes, removeCardTypes, removeSubTypes, + addChangedCardTypes(addType, removeType, addAllCreatureTypes, removeSuperTypes, removeCardTypes, removeSubTypes, removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes, timestamp, staticId, updateView, cda); } @@ -4457,7 +4454,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } } - this.changedTypeByText = new CardChangedType(new CardType(toAdd, true), new CardType(toRemove, true), false, false, false, false, false, false, false); + this.changedTypeByText = new CardChangedType(new CardType(toAdd, true), new CardType(toRemove, true), false, false, false, false, false, false, false, false); currentState.updateChangedText(); @@ -4474,7 +4471,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { final List addKeywords = Lists.newArrayList(); final List removeKeywords = Lists.newArrayList(); // Text Change for intrinsic keywords - for(KeywordInterface kw : beforeKeywords) { + for (KeywordInterface kw : beforeKeywords) { String oldtxt = kw.getOriginal(); final String newtxt = AbilityUtils.applyKeywordTextChangeEffects(oldtxt, this); if (!newtxt.equals(oldtxt)) { @@ -4562,6 +4559,9 @@ public class Card extends GameEntity implements Comparable, IHasSVars { public final Iterable getHiddenExtrinsicKeywords() { return Iterables.concat(this.hiddenExtrinsicKeywords.values()); } + public final Table> getHiddenExtrinsicKeywordsTable() { + return hiddenExtrinsicKeywords; + } public final void addHiddenExtrinsicKeywords(long timestamp, long staticId, Iterable keywords) { // TODO if some keywords aren't removed anymore, then no need for extra Array List @@ -4660,11 +4660,11 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public final boolean isPermanent() { - return !isImmutable() && (isInZone(ZoneType.Battlefield) || getType().isPermanent()); + return !isImmutable() && (isInPlay() || getType().isPermanent()); } public final boolean isSpell() { - return (isInstant() || isSorcery() || (isAura() && !isInZone((ZoneType.Battlefield)))); + return isInstant() || isSorcery() || (isAura() && !isInZone((ZoneType.Battlefield))); } public final boolean isLand() { return getType().isLand(); } @@ -5139,12 +5139,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public final boolean hasABasicLandType() { - for (final String type : getType().getSubtypes()) { - if (forge.card.CardType.isABasicLandType(type)) { - return true; - } - } - return false; + return Iterables.any(getType().getSubtypes(), CardType.Predicates.IS_BASIC_LAND_TYPE); } public final boolean isUsedToPay() { @@ -5639,7 +5634,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { bestowTimestamp = getGame().getNextTimestamp(); addChangedCardTypes(new CardType(Collections.singletonList("Aura"), true), new CardType(Collections.singletonList("Creature"), true), - false, false, false, false, false, false, true, bestowTimestamp, 0, updateView, false); + false, false, false, false, false, false, false, true, bestowTimestamp, 0, updateView, false); addChangedCardKeywords(Collections.singletonList("Enchant creature"), Lists.newArrayList(), false, bestowTimestamp, 0, updateView); } @@ -5749,7 +5744,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } // Protection only works on the Battlefield - if (!isInZone(ZoneType.Battlefield)) { + if (!isInPlay()) { return false; } @@ -5975,7 +5970,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } // keywords don't work outside battlefield - if (!isInZone(ZoneType.Battlefield)) { + if (!isInPlay()) { return true; } @@ -6324,7 +6319,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { public boolean isCommander() { if (this.getMeldedWith() != null && this.getMeldedWith().isCommander()) return true; - if (isInZone(ZoneType.Battlefield) && hasMergedCard()) { + if (isInPlay() && hasMergedCard()) { for (final Card c : getMergedCards()) if (c.isCommander) return true; } @@ -6346,7 +6341,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { return this; if (this.getMeldedWith() != null && this.getMeldedWith().isCommander()) return this.getMeldedWith(); - if (isInZone(ZoneType.Battlefield) && hasMergedCard()) { + if (isInPlay() && hasMergedCard()) { for (final Card c : getMergedCards()) if (c.isCommander) return c; } diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index 824e9c9bf01..3f294a24501 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -816,7 +816,7 @@ public class CardFactory { if (sa.hasParam("SetCreatureTypes")) { // currently only Changeling and similar should be affected by that // other cards using AddType$ ChosenType should not - if (sta.hasParam("AddType") && CardType.AllCreatureTypes.equals(sta.getParam("AddType"))) { + if (sta.hasParam("AddAllCreatureTypes")) { state.removeStaticAbility(sta); } } diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index fffd9b688bc..73103b937b7 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -38,6 +38,7 @@ import com.google.common.collect.Sets; import forge.card.CardStateName; import forge.card.CardType; +import forge.card.CardTypeView; import forge.card.ColorSet; import forge.card.ICardFace; import forge.card.MagicColor; @@ -448,12 +449,14 @@ public class CardFactoryUtil { final Map map = Maps.newHashMap(); for (final Card c : list) { // Remove Duplicated types - final Set creatureTypes = c.getType().getCreatureTypes(); - if (creatureTypes.contains(CardType.AllCreatureTypes)) { + CardTypeView type = c.getType(); + if (type.hasAllCreatureTypes() && Iterables.isEmpty(type.getExcludedCreatureSubTypes())) { allCreatureType++; continue; } - for (String creatureType : creatureTypes) { + // if something has all creature types, but some are excluded, the count might be messed up + + for (String creatureType : type.getCreatureTypes()) { Integer count = map.get(creatureType); map.put(creatureType, count == null ? 1 : count + 1); } @@ -477,16 +480,15 @@ public class CardFactoryUtil { * a {@link forge.game.card.CardCollection} object. * @return a string. */ - public static String[] getMostProminentCreatureType(final CardCollectionView list) { + public static Iterable getMostProminentCreatureType(final CardCollectionView list) { if (list.isEmpty()) { - return null; + return ImmutableList.of(); } final Map map = Maps.newHashMap(); for (final Card c : list) { // Remove Duplicated types - final Set creatureTypes = c.getType().getCreatureTypes(); - for (String creatureType : creatureTypes) { + for (String creatureType : c.getType().getCreatureTypes()) { Integer count = map.get(creatureType); map.put(creatureType, count == null ? 1 : count + 1); } @@ -499,16 +501,16 @@ public class CardFactoryUtil { } } if (max == 0) { - return null; + return ImmutableList.of(); } - StringBuilder sb = new StringBuilder(); + List result = Lists.newArrayList(); for (final Entry entry : map.entrySet()) { if (max == entry.getValue()) { - sb.append(entry.getKey()).append(","); + result.add(entry.getKey()); } } - return sb.toString().split(","); + return result; } /** @@ -718,8 +720,7 @@ public class CardFactoryUtil { return validSource; } - public static ReplacementEffect makeEtbCounter(final String kw, final CardState card, final boolean intrinsic) - { + public static ReplacementEffect makeEtbCounter(final String kw, final CardState card, final boolean intrinsic) { String parse = kw; String[] splitkw = parse.split(":"); @@ -1859,7 +1860,7 @@ public class CardFactoryUtil { inst.addTrigger(parsedPlayTrigger); } else if (keyword.equals("Training")) { final String trigStr = "Mode$ Attacks | ValidCard$ Card.Self | Secondary$ True | " + - "IsPresent$ Creature.attacking+Other+powerGTX | TriggerDescription$ Training (" + + "IsPresent$ Creature.attacking+Other+powerGTX | NoResolvingCheck$ True | TriggerDescription$ Training (" + inst.getReminderText() + ")"; final String effect = "DB$ PutCounter | CounterType$ P1P1 | CounterNum$ 1 | Defined$ Self | Training$ True"; @@ -1871,7 +1872,6 @@ public class CardFactoryUtil { trigger.setOverridingAbility(sa); inst.addTrigger(trigger); - } else if (keyword.startsWith("Tribute")) { // use hardcoded ability name final String abStr = "TrigNotTribute"; @@ -3422,7 +3422,7 @@ public class CardFactoryUtil { svars.put("AffinityX", "Count$Valid " + t + ".YouCtrl"); } else if (keyword.equals("Changeling")) { effect = "Mode$ Continuous | EffectZone$ All | Affected$ Card.Self" + - " | CharacteristicDefining$ True | AddType$ AllCreatureTypes | Secondary$ True" + + " | CharacteristicDefining$ True | AddAllCreatureTypes$ True | Secondary$ True" + " | Description$ Changeling (" + inst.getReminderText() + ")"; } else if (keyword.equals("Cipher")) { StringBuilder sb = new StringBuilder(); @@ -3599,7 +3599,7 @@ public class CardFactoryUtil { } altCostSA.setRestrictions(restriction); - String costDescription = TextUtil.fastReplace(params.get("Description"),"CARDNAME", card.getName()); + String costDescription = TextUtil.fastReplace(params.get("Description"), "CARDNAME", card.getName()); if (costDescription == null || costDescription.isEmpty()) { costDescription = TextUtil.concatWithSpace("You may", abCost.toStringAlt(), "rather than pay", TextUtil.addSuffix(card.getName(), "'s mana cost.")); } diff --git a/forge-game/src/main/java/forge/game/card/CardProperty.java b/forge-game/src/main/java/forge/game/card/CardProperty.java index 9063f5291ad..ba3ab337c9f 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -755,12 +755,9 @@ public class CardProperty { } } else if (property.startsWith("MostProminentCreatureTypeInLibrary")) { final CardCollectionView list = sourceController.getCardsIn(ZoneType.Library); - String[] type = CardFactoryUtil.getMostProminentCreatureType(list); - if (type != null) { - for (String s : type) { - if (!card.getType().hasCreatureType(s)) { - return false; - } + for (String s : CardFactoryUtil.getMostProminentCreatureType(list)) { + if (!card.getType().hasCreatureType(s)) { + return false; } } } else if (property.startsWith("sharesCreatureTypeWith")) { diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index a23e834f198..5cced7cc806 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -874,7 +874,7 @@ public class CardView extends GameEntityView { set(TrackableProperty.Modal, c.isModal()); //backside - if (c.getAlternateState()!=null) + if (c.getAlternateState() != null) updateBackSide(c.getAlternateState().getName(), c.hasBackSide()); final Card cloner = c.getCloner(); diff --git a/forge-game/src/main/java/forge/game/card/token/TokenInfo.java b/forge-game/src/main/java/forge/game/card/token/TokenInfo.java index 32c977ce5a2..4e764b3663f 100644 --- a/forge-game/src/main/java/forge/game/card/token/TokenInfo.java +++ b/forge-game/src/main/java/forge/game/card/token/TokenInfo.java @@ -185,11 +185,9 @@ public class TokenInfo { } } if (!typeMap.isEmpty()) { - String oldName = result.getName(); CardType type = new CardType(result.getType()); - String joinedName = StringUtils.join(type.getSubtypes(), " "); - final boolean nameGenerated = oldName.equals(joinedName); + final boolean nameGenerated = result.getName().endsWith(" Token"); boolean typeChanged = false; if (!Iterables.isEmpty(type.getSubtypes())) { @@ -207,7 +205,7 @@ public class TokenInfo { // update generated Name if (nameGenerated) { - result.setName(StringUtils.join(type.getSubtypes(), " ")); + result.setName(StringUtils.join(type.getSubtypes(), " ") + " Token"); } } } diff --git a/forge-game/src/main/java/forge/game/combat/AttackConstraints.java b/forge-game/src/main/java/forge/game/combat/AttackConstraints.java index ef6499e1c81..2c1d89da64e 100644 --- a/forge-game/src/main/java/forge/game/combat/AttackConstraints.java +++ b/forge-game/src/main/java/forge/game/combat/AttackConstraints.java @@ -47,7 +47,7 @@ public class AttackConstraints { public AttackConstraints(final Combat combat) { final Game game = combat.getAttackingPlayer().getGame(); - possibleAttackers = CardLists.filter(combat.getAttackingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); + possibleAttackers = combat.getAttackingPlayer().getCreaturesInPlay(); possibleDefenders = combat.getDefenders(); globalRestrictions = GlobalAttackRestrictions.getGlobalRestrictions(combat.getAttackingPlayer(), possibleDefenders); diff --git a/forge-game/src/main/java/forge/game/combat/CombatUtil.java b/forge-game/src/main/java/forge/game/combat/CombatUtil.java index ea49ca6afd5..d32139d49f3 100644 --- a/forge-game/src/main/java/forge/game/combat/CombatUtil.java +++ b/forge-game/src/main/java/forge/game/combat/CombatUtil.java @@ -1036,7 +1036,7 @@ public class CombatUtil { * @return a boolean. */ public static boolean canBlock(final Card attacker, final Card blocker, final boolean nextTurn) { - if ((attacker == null) || (blocker == null)) { + if (attacker == null || blocker == null) { return false; } diff --git a/forge-game/src/main/java/forge/game/cost/CostReveal.java b/forge-game/src/main/java/forge/game/cost/CostReveal.java index 470cec17b42..909e07573f7 100644 --- a/forge-game/src/main/java/forge/game/cost/CostReveal.java +++ b/forge-game/src/main/java/forge/game/cost/CostReveal.java @@ -77,7 +77,6 @@ public class CostReveal extends CostPartWithList { return handList.size(); } - @Override public final boolean canPay(final SpellAbility ability, final Player payer) { final Card source = ability.getHostCard(); diff --git a/forge-game/src/main/java/forge/game/mana/Mana.java b/forge-game/src/main/java/forge/game/mana/Mana.java index 92f061eb248..5f7b90d2d46 100644 --- a/forge-game/src/main/java/forge/game/mana/Mana.java +++ b/forge-game/src/main/java/forge/game/mana/Mana.java @@ -23,7 +23,6 @@ import forge.game.card.Card; import forge.game.card.CardUtil; import forge.game.spellability.AbilityManaPart; import forge.game.spellability.SpellAbility; -import forge.game.zone.ZoneType; /** *

@@ -72,7 +71,7 @@ public class Mana { public Mana(final byte color, final Card source, final AbilityManaPart manaAbility) { this.color = color; this.manaAbility = manaAbility; - this.sourceCard = source.isInZone(ZoneType.Battlefield) ? CardUtil.getLKICopy(source) : source.getGame().getChangeZoneLKIInfo(source); + this.sourceCard = source.isInPlay() ? CardUtil.getLKICopy(source) : source.getGame().getChangeZoneLKIInfo(source); } @Override diff --git a/forge-game/src/main/java/forge/game/mana/ManaPool.java b/forge-game/src/main/java/forge/game/mana/ManaPool.java index 2f890d8c5d1..3fe18c50722 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaPool.java +++ b/forge-game/src/main/java/forge/game/mana/ManaPool.java @@ -6,21 +6,21 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package forge.game.mana; -import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.apache.commons.lang3.StringUtils; @@ -28,24 +28,28 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; -import forge.card.MagicColor; import forge.card.mana.ManaAtom; import forge.card.mana.ManaCostShard; +import forge.game.Game; import forge.game.GlobalRuleChange; +import forge.game.ability.AbilityKey; import forge.game.event.EventValueChangeType; import forge.game.event.GameEventManaPool; import forge.game.event.GameEventZone; import forge.game.phase.PhaseType; import forge.game.player.Player; +import forge.game.replacement.ReplacementLayer; +import forge.game.replacement.ReplacementType; import forge.game.spellability.AbilityManaPart; import forge.game.spellability.SpellAbility; +import forge.game.staticability.StaticAbilityUnspentMana; import forge.game.zone.ZoneType; /** *

* ManaPool class. *

- * + * * @author Forge * @version $Id$ */ @@ -64,9 +68,14 @@ public class ManaPool extends ManaConversionMatrix implements Iterable { } public void addMana(final Mana mana) { + addMana(mana, true); + } + public void addMana(final Mana mana, boolean updateView) { floatingMana.put(mana.getColor(), mana); - owner.updateManaForView(); - owner.getGame().fireEvent(new GameEventManaPool(owner, EventValueChangeType.Added, mana)); + if (updateView) { + owner.updateManaForView(); + owner.getGame().fireEvent(new GameEventManaPool(owner, EventValueChangeType.Added, mana)); + } } public final void add(final Iterable manaList) { @@ -78,47 +87,55 @@ public class ManaPool extends ManaConversionMatrix implements Iterable { /** *

* willManaBeLostAtEndOfPhase. - * + * * @return - whether floating mana will be lost if the current phase ended right now *

*/ public final boolean willManaBeLostAtEndOfPhase() { - if (floatingMana.isEmpty() || - owner.getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.manapoolsDontEmpty) || - owner.hasKeyword("Convert unused mana to Colorless")) { + if (floatingMana.isEmpty()) { + return false; + } + + final Map runParams = AbilityKey.mapFromAffected(owner); + if (!owner.getGame().getReplacementHandler().getReplacementList(ReplacementType.LoseMana, runParams, ReplacementLayer.Other).isEmpty()) { return false; } int safeMana = 0; - for (final byte c : MagicColor.WUBRG) { - final String captName = StringUtils.capitalize(MagicColor.toLongString(c)); - if (owner.hasKeyword(captName + " mana doesn't empty from your mana pool as steps and phases end.")) { - safeMana += getAmountOfColor(c); - } + for (final byte c : StaticAbilityUnspentMana.getManaToKeep(owner)) { + safeMana += getAmountOfColor(c); } return totalMana() != safeMana; //won't lose floating mana if all mana is of colors that aren't going to be emptied } + public final boolean hasBurn() { + final Game game = owner.getGame(); + return game.getRules().hasManaBurn() || game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.manaBurn); + } + public final List clearPool(boolean isEndOfPhase) { // isEndOfPhase parameter: true = end of phase, false = mana drain effect - List cleared = new ArrayList<>(); + List cleared = Lists.newArrayList(); if (floatingMana.isEmpty()) { return cleared; } - if (isEndOfPhase && owner.getGame().getStaticEffects().getGlobalRuleChange(GlobalRuleChange.manapoolsDontEmpty)) { - return cleared; - } + boolean convertToColorless = false; - final boolean convertToColorless = owner.hasKeyword("Convert unused mana to Colorless"); + final Map runParams = AbilityKey.mapFromAffected(owner); + switch (owner.getGame().getReplacementHandler().run(ReplacementType.LoseMana, runParams)) { + case NotReplaced: + break; + case Skipped: + return cleared; + default: // the only ones that does replace losing Mana are making it colorless instead + convertToColorless = true; + break; + + } final List keys = Lists.newArrayList(floatingMana.keySet()); if (isEndOfPhase) { - for (final Byte c : Lists.newArrayList(keys)) { - final String captName = StringUtils.capitalize(MagicColor.toLongString(c)); - if (owner.hasKeyword(captName + " mana doesn't empty from your mana pool as steps and phases end.")) { - keys.remove(c); - } - } + keys.removeAll(StaticAbilityUnspentMana.getManaToKeep(owner)); } if (convertToColorless) { keys.remove(Byte.valueOf((byte)ManaAtom.COLORLESS)); @@ -126,29 +143,22 @@ public class ManaPool extends ManaConversionMatrix implements Iterable { for (Byte b : keys) { Collection cm = floatingMana.get(b); + final List pMana = Lists.newArrayList(); if (isEndOfPhase && !owner.getGame().getPhaseHandler().is(PhaseType.CLEANUP)) { - final List pMana = new ArrayList<>(); for (final Mana mana : cm) { if (mana.getManaAbility()!= null && mana.getManaAbility().isPersistentMana()) { pMana.add(mana); } } - cm.removeAll(pMana); - if (convertToColorless) { - convertManaColor(b, (byte)ManaAtom.COLORLESS); - cm.addAll(pMana); - } else { - cleared.addAll(cm); - cm.clear(); - floatingMana.putAll(b, pMana); - } + } + cm.removeAll(pMana); + if (convertToColorless) { + convertManaColor(b, (byte)ManaAtom.COLORLESS); + cm.addAll(pMana); } else { - if (convertToColorless) { - convertManaColor(b, (byte)ManaAtom.COLORLESS); - } else { - cleared.addAll(cm); - cm.clear(); - } + cleared.addAll(cm); + cm.clear(); + floatingMana.putAll(b, pMana); } } @@ -158,7 +168,7 @@ public class ManaPool extends ManaConversionMatrix implements Iterable { } private void convertManaColor(final byte originalColor, final byte toColor) { - List convert = new ArrayList<>(); + List convert = Lists.newArrayList(); Collection cm = floatingMana.get(originalColor); for (Mana m : cm) { convert.add(new Mana(toColor, m.getSourceCard(), m.getManaAbility())); @@ -168,8 +178,11 @@ public class ManaPool extends ManaConversionMatrix implements Iterable { owner.updateManaForView(); } - private boolean removeMana(final Mana mana) { - if (floatingMana.remove(mana.getColor(), mana)) { + public boolean removeMana(final Mana mana) { + return removeMana(mana, true); + } + public boolean removeMana(final Mana mana, boolean updateView) { + if (floatingMana.remove(mana.getColor(), mana) && updateView) { owner.updateManaForView(); owner.getGame().fireEvent(new GameEventManaPool(owner, EventValueChangeType.Removed, mana)); return true; @@ -249,7 +262,7 @@ public class ManaPool extends ManaConversionMatrix implements Iterable { return false; } - final List removeFloating = new ArrayList<>(); + final List removeFloating = Lists.newArrayList(); boolean manaNotAccountedFor = false; // loop over mana produced by mana ability @@ -333,4 +346,5 @@ public class ManaPool extends ManaConversionMatrix implements Iterable { public Iterator iterator() { return floatingMana.values().iterator(); } + } diff --git a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java index aa976ed0cb9..20c795e9fa8 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -309,6 +309,7 @@ public class PhaseHandler implements java.io.Serializable { break; case COMBAT_BEGIN: + nCombatsThisTurn++; combat = new Combat(playerTurn); //PhaseUtil.verifyCombat(); break; @@ -478,9 +479,7 @@ public class PhaseHandler implements java.io.Serializable { for (Player p : game.getPlayers()) { int burn = p.getManaPool().clearPool(true).size(); - boolean manaBurns = game.getRules().hasManaBurn() || - (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.manaBurn)); - if (manaBurns) { + if (p.getManaPool().hasBurn()) { p.loseLife(burn, false, true); } } @@ -605,7 +604,6 @@ public class PhaseHandler implements java.io.Serializable { return; } - nCombatsThisTurn++; // Reset all active Triggers game.getTriggerHandler().resetActiveTriggers(); @@ -981,15 +979,18 @@ public class PhaseHandler implements java.io.Serializable { } public final boolean isFirstCombat() { - return (nCombatsThisTurn == 1); + return nCombatsThisTurn == 1; + } + public final int getNumCombat() { + return nCombatsThisTurn; } public final boolean isFirstUpkeep() { - return is(PhaseType.UPKEEP) && (nUpkeepsThisTurn == 0); + return is(PhaseType.UPKEEP) && nUpkeepsThisTurn == 0; } public final boolean isFirstUpkeepThisGame() { - return is(PhaseType.UPKEEP) && (nUpkeepsThisGame == 0); + return is(PhaseType.UPKEEP) && nUpkeepsThisGame == 0; } public final boolean isPreCombatMain() { @@ -998,7 +999,7 @@ public class PhaseHandler implements java.io.Serializable { } public final boolean beforeFirstPostCombatMainEnd() { - return (nMain2sThisTurn == 0); + return nMain2sThisTurn == 0; } private final static boolean DEBUG_PHASES = false; @@ -1164,11 +1165,17 @@ public class PhaseHandler implements java.io.Serializable { } public final boolean devAdvanceToPhase(PhaseType targetPhase) { + return devAdvanceToPhase(targetPhase, null); + } + public final boolean devAdvanceToPhase(PhaseType targetPhase, Runnable resolver) { boolean isTopsy = playerTurn.getAmountOfKeyword("The phases of your turn are reversed.") % 2 == 1; while (phase.isBefore(targetPhase, isTopsy)) { if (checkStateBasedEffects()) { return false; } + if (resolver != null) { + resolver.run(); + } onPhaseEnd(); advanceToNextPhase(); onPhaseBegin(); diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 6ad07f3c382..8f89b8e00a8 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -105,6 +105,7 @@ import forge.game.spellability.SpellAbility; import forge.game.staticability.StaticAbility; import forge.game.staticability.StaticAbilityCantBeCast; import forge.game.staticability.StaticAbilityCantDraw; +import forge.game.staticability.StaticAbilityCantGainLosePayLife; import forge.game.staticability.StaticAbilityCantPutCounter; import forge.game.trigger.Trigger; import forge.game.trigger.TriggerHandler; @@ -539,7 +540,7 @@ public class Player extends GameEntity implements Comparable { } public final boolean canGainLife() { - return !hasLost() && !hasKeyword("You can't gain life.") && !hasKeyword("Your life total can't change."); + return !hasLost() && !StaticAbilityCantGainLosePayLife.anyCantGainLife(this); } public final int loseLife(int toLose, final boolean damage, final boolean manaBurn) { @@ -607,14 +608,14 @@ public class Player extends GameEntity implements Comparable { } public final boolean canLoseLife() { - return !hasLost() && !hasKeyword("Your life total can't change."); + return !hasLost() && !StaticAbilityCantGainLosePayLife.anyCantLosePayLife(this); } public final boolean canPayLife(final int lifePayment) { if (lifePayment > 0 && life < lifePayment) { return false; } - return (lifePayment <= 0) || !hasKeyword("Your life total can't change."); + return (lifePayment <= 0) || !StaticAbilityCantGainLosePayLife.anyCantLosePayLife(this); } public final boolean payLife(final int lifePayment, final Card source) { @@ -2146,9 +2147,6 @@ public class Player extends GameEntity implements Comparable { } public final boolean hasProwl(final String type) { - if (prowl.contains(CardType.AllCreatureTypes)) { - return true; - } return prowl.contains(type); } public final void addProwlType(final String type) { diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceLoseMana.java b/forge-game/src/main/java/forge/game/replacement/ReplaceLoseMana.java new file mode 100644 index 00000000000..8b888be7462 --- /dev/null +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceLoseMana.java @@ -0,0 +1,52 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge.game.replacement; + +import java.util.Map; + +import forge.game.ability.AbilityKey; +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; + +public class ReplaceLoseMana extends ReplacementEffect { + + public ReplaceLoseMana(Map map, Card host, boolean intrinsic) { + super(map, host, intrinsic); + } + + /* (non-Javadoc) + * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) + */ + @Override + public boolean canReplace(Map runParams) { + if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Affected))) { + return false; + } + + return true; + } + + /* (non-Javadoc) + * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility) + */ + @Override + public void setReplacingObjects(Map runParams, SpellAbility sa) { + sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected)); + } + +} diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java index a0e2011a456..e71dcb07162 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementEffect.java @@ -223,8 +223,7 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { String currentName; if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) { currentName = cardState.getName(); - } - else { + } else { currentName = getHostCard().getName(); } desc = CardTranslation.translateSingleDescriptionText(desc, currentName); diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java index 10187567ef5..7d8eed43a24 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java @@ -278,9 +278,6 @@ public class ReplacementHandler { // Log there String message = chosenRE.getDescription(); if (!StringUtils.isEmpty(message)) { - if (chosenRE.getHostCard() != null) { - message = TextUtil.fastReplace(message, "CARDNAME", chosenRE.getHostCard().getName()); - } game.getGameLog().add(GameLogEntryType.EFFECT_REPLACED, message); } @@ -365,17 +362,17 @@ public class ReplacementHandler { // Decider gets to choose whether or not to apply the replacement. if (replacementEffect.hasParam("Optional")) { Player optDecider = decider; - if (replacementEffect.hasParam("OptionalDecider") && (effectSA != null)) { + if (replacementEffect.hasParam("OptionalDecider") && effectSA != null) { effectSA.setActivatingPlayer(host.getController()); optDecider = AbilityUtils.getDefinedPlayers(host, replacementEffect.getParam("OptionalDecider"), effectSA).get(0); } - Card cardForUi = host.getCardForUi(); - String effectDesc = TextUtil.fastReplace(replacementEffect.getDescription(), "CARDNAME", CardTranslation.getTranslatedName(cardForUi.getName())); + String name = CardTranslation.getTranslatedName(host.getCardForUi().getName()); + String effectDesc = TextUtil.fastReplace(replacementEffect.getDescription(), "CARDNAME", name); final String question = replacementEffect instanceof ReplaceDiscard - ? Localizer.getInstance().getMessage("lblApplyCardReplacementEffectToCardConfirm", CardTranslation.getTranslatedName(cardForUi.getName()), runParams.get(AbilityKey.Card).toString(), effectDesc) - : Localizer.getInstance().getMessage("lblApplyReplacementEffectOfCardConfirm", CardTranslation.getTranslatedName(cardForUi.getName()), effectDesc); + ? Localizer.getInstance().getMessage("lblApplyCardReplacementEffectToCardConfirm", name, runParams.get(AbilityKey.Card).toString(), effectDesc) + : Localizer.getInstance().getMessage("lblApplyReplacementEffectOfCardConfirm", name, effectDesc); GameEntity affected = (GameEntity) runParams.get(AbilityKey.Affected); boolean confirmed = optDecider.getController().confirmReplacementEffect(replacementEffect, effectSA, affected, question); if (!confirmed) { @@ -403,7 +400,6 @@ public class ReplacementHandler { if ("True".equals(replacementEffect.getParam("Skip"))) { return ReplacementResult.Skipped; // Event is skipped. } - Player player = host.getController(); if (effectSA != null) { @@ -422,6 +418,10 @@ public class ReplacementHandler { } } + if ("Replaced".equals(replacementEffect.getParam("ReplacementResult"))) { + return ReplacementResult.Replaced; // Event is replaced without SA. + } + // if the spellability is a replace effect then its some new logic // if ReplacementResult is set in run params use that instead if (runParams.containsKey(AbilityKey.ReplacementResult)) { diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java index b63f9377961..2c9b8cc3700 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java @@ -30,6 +30,7 @@ public enum ReplacementType { GameLoss(ReplaceGameLoss.class), Learn(ReplaceLearn.class), LifeReduced(ReplaceLifeReduced.class), + LoseMana(ReplaceLoseMana.class), Mill(ReplaceMill.class), Moved(ReplaceMoved.class), ProduceMana(ReplaceProduceMana.class), diff --git a/forge-game/src/main/java/forge/game/spellability/LandAbility.java b/forge-game/src/main/java/forge/game/spellability/LandAbility.java index f02d2143c47..04f2c3e60ce 100644 --- a/forge-game/src/main/java/forge/game/spellability/LandAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/LandAbility.java @@ -26,7 +26,6 @@ import forge.game.card.CardUtil; import forge.game.cost.Cost; import forge.game.player.Player; import forge.game.staticability.StaticAbility; -import forge.game.zone.ZoneType; public class LandAbility extends Ability { @@ -78,7 +77,7 @@ public class LandAbility extends Ability { getMayPlay().incMayPlayTurn(); } // if land isn't in battlefield try to reset the card state - if (result != null && !result.isInZone(ZoneType.Battlefield)) { + if (result != null && !result.isInPlay()) { result.setState(CardStateName.Original, true); } } diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 453f28847f4..ece876bceff 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -59,10 +59,12 @@ import forge.game.card.CardPredicates; import forge.game.card.CardZoneTable; import forge.game.cost.Cost; import forge.game.cost.CostPart; +import forge.game.cost.CostTap; import forge.game.event.GameEventCardStatsChanged; import forge.game.keyword.Keyword; import forge.game.mana.Mana; import forge.game.mana.ManaCostBeingPaid; +import forge.game.phase.Untap; import forge.game.player.Player; import forge.game.player.PlayerCollection; import forge.game.replacement.ReplacementEffect; @@ -2204,8 +2206,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit int score = 0; if (manaPart == null) { score++; //Assume a mana ability can generate at least 1 mana if the amount of mana can't be determined now. - } - else { + } else { String mana = manaPart.mana(); if (!mana.equals("Any")) { score += mana.length(); @@ -2213,8 +2214,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit // Producing colorless should produce a slightly lower score score += 1; } - } - else { + } else { score += 7; } } @@ -2227,6 +2227,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit if (!costPart.isRenewable()) { score += 3; } + if (costPart instanceof CostTap && !Untap.canUntap(getHostCard())) { + score += 10; + } // Increase score by 1 for each costpart in general score++; } diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java index 8b4966d853f..ca779eefe7a 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java @@ -134,6 +134,10 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { this.setPhases(PhaseType.parseRange(params.get("ActivationPhases"))); } + if (params.containsKey("ActivationFirstCombat")) { + this.setFirstCombatOnly(true); + } + if (params.containsKey("ActivationGameTypes")) { this.setGameTypes(GameType.listValueOf(params.get("ActivationGameTypes"))); } @@ -207,7 +211,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { // for Bestow need to check the animated State if (sa.isSpell() && sa.isBestow()) { // already bestowed or in battlefield, no need to check for spell - if (c.isInZone(ZoneType.Battlefield)) { + if (c.isInPlay()) { return false; } @@ -319,6 +323,12 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { return false; } } + + if (this.getFirstCombatOnly()) { + if (game.getPhaseHandler().getNumCombat() > 1) { + return false; + } + } return true; } @@ -480,7 +490,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { // 702.36e // If the permanent wouldn’t have a morph cost if it were face up, it can’t be turned face up this way. - if (sa.isMorphUp() && c.isInZone(ZoneType.Battlefield)) { + if (sa.isMorphUp() && c.isInPlay()) { Card cp = c; if (!c.isLKI()) { cp = CardUtil.getLKICopy(c); diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java index c8b2d3215f1..814eecda2fb 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java @@ -58,6 +58,7 @@ public class SpellAbilityVariables implements Cloneable { public void setVariables(SpellAbilityVariables sav) { this.zone = sav.getZone(); this.phases = Sets.newEnumSet(sav.getPhases(), PhaseType.class); + this.firstCombatOnly = sav.getFirstCombatOnly(); this.gameTypes = Sets.newEnumSet(sav.getGameTypes(), GameType.class); this.sorcerySpeed = sav.isSorcerySpeed(); this.instantSpeed = sav.isInstantSpeed(); @@ -104,6 +105,8 @@ public class SpellAbilityVariables implements Cloneable { /** The phases. */ private Set phases = EnumSet.noneOf(PhaseType.class); + private boolean firstCombatOnly = false; + /** The GameTypes */ private Set gameTypes = EnumSet.noneOf(GameType.class); @@ -695,10 +698,22 @@ public class SpellAbilityVariables implements Cloneable { return this.phases; } + /** + * Gets the first combat. + * + * @return first combat + */ + public final boolean getFirstCombatOnly() { + return this.firstCombatOnly; + } + public final boolean setFirstCombatOnly(boolean first) { + return this.firstCombatOnly = first; + } + /** * Gets the game types. * - * @return the phases + * @return the game types */ public final Set getGameTypes() { return this.gameTypes; diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java index 778a5f27d49..78b2f9ce273 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbility.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbility.java @@ -148,6 +148,7 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone } if (hasParam("AddType") || hasParam("RemoveType") + || hasParam("AddAllCreatureTypes") || hasParam("RemoveCardTypes") || hasParam("RemoveSubTypes") || hasParam("RemoveSuperTypes") || hasParam("RemoveLandTypes") || hasParam("RemoveCreatureTypes") || hasParam("RemoveArtifactTypes") @@ -208,8 +209,7 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone String currentName; if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) { currentName = cardState.getName(); - } - else { + } else { currentName = getHostCard().getName(); } String desc = CardTranslation.translateSingleDescriptionText(getParam("Description"), currentName); @@ -432,7 +432,7 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone } } } else if (!hasParam("CharacteristicDefining")) { - if (!getHostCard().isInZone(ZoneType.Battlefield)) { // default + if (!getHostCard().isInPlay()) { // default return false; } } diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityAdapt.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityAdapt.java index e052d645a69..b1507945a95 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityAdapt.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityAdapt.java @@ -23,7 +23,6 @@ public class StaticAbilityAdapt { } return false; } - public static boolean applyWithAdapt(final StaticAbility stAb, final SpellAbility sa, final Card card) { if (!stAb.matchesValidParam("ValidCard", card)) { diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java index f298d3ef624..a466761a774 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java @@ -171,23 +171,6 @@ public class StaticAbilityCantBeCast { return false; } - // TODO refactor this ones using ValidSA above - if (stAb.hasParam("NonMana") && (spellAbility.isManaAbility())) { - return false; - } - - if (stAb.hasParam("NonLoyalty") && spellAbility.isPwAbility()) { - return false; - } - - if (stAb.hasParam("Loyalty") && !spellAbility.isPwAbility()) { - return false; - } - - if (stAb.hasParam("TapAbility") && !(spellAbility.getPayCosts().hasTapCost())) { - return false; - } - if (stAb.hasParam("NonActivatorTurn") && (activator != null) && activator.getGame().getPhaseHandler().isPlayerTurn(activator)) { return false; diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantGainLosePayLife.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantGainLosePayLife.java new file mode 100644 index 00000000000..59cfaeecf8d --- /dev/null +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantGainLosePayLife.java @@ -0,0 +1,54 @@ +package forge.game.staticability; + +import forge.game.Game; +import forge.game.card.Card; +import forge.game.player.Player; +import forge.game.zone.ZoneType; + +public class StaticAbilityCantGainLosePayLife { + + static String MODE_CANT_GAIN_LIFE = "CantGainLife"; + static String MODE_CANT_CHANGE_LIFE = "CantChangeLife"; + + public static boolean anyCantGainLife(final Player player) { + final Game game = player.getGame(); + for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { + for (final StaticAbility stAb : ca.getStaticAbilities()) { + if (stAb.isSuppressed() || !stAb.checkConditions()) { + continue; + } + if (!(stAb.getParam("Mode").equals(MODE_CANT_GAIN_LIFE) || stAb.getParam("Mode").equals(MODE_CANT_CHANGE_LIFE))) { + continue; + } + + if (applyCommonAbility(stAb, player)) { + return true; + } + } + } + return false; + } + + public static boolean anyCantLosePayLife(final Player player) { + final Game game = player.getGame(); + for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { + for (final StaticAbility stAb : ca.getStaticAbilities()) { + if (!stAb.getParam("Mode").equals(MODE_CANT_CHANGE_LIFE) || stAb.isSuppressed() || !stAb.checkConditions()) { + continue; + } + + if (applyCommonAbility(stAb, player)) { + return true; + } + } + } + return false; + } + + public static boolean applyCommonAbility(final StaticAbility stAb, final Player player) { + if (!stAb.matchesValidParam("ValidPlayer", player)) { + return false; + } + return true; + } +} diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantTarget.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantTarget.java index 2e67893bc55..fc0aa270f94 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantTarget.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantTarget.java @@ -61,17 +61,15 @@ public class StaticAbilityCantTarget { return false; } } else { // default zone is battlefield - if (!card.isInZone(ZoneType.Battlefield)) { + if (!card.isInPlay()) { return false; } } - if (!stAb.matchesValidParam("ValidCard", card)) { return false; } - if (stAb.hasParam("Hexproof") && (activator != null)) { for (KeywordInterface kw : activator.getKeywords()) { String k = kw.getOriginal(); diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index af3e7614277..f9512018a0f 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -140,6 +140,7 @@ public final class StaticAbilityContinuous { String[] addStatics = null; boolean removeAllAbilities = false; boolean removeNonMana = false; + boolean addAllCreatureTypes = false; boolean removeSuperTypes = false; boolean removeCardTypes = false; boolean removeSubTypes = false; @@ -426,6 +427,9 @@ public final class StaticAbilityContinuous { } }); } + if (params.containsKey("AddAllCreatureTypes")) { + addAllCreatureTypes = true; + } if (params.containsKey("RemoveSuperTypes")) { removeSuperTypes = true; } @@ -855,11 +859,7 @@ public final class StaticAbilityContinuous { if (params.containsKey("TriggerRememberDefined")) { String triggerRemembered = (params.get("TriggerRememberDefined")); for (final String rem : triggerRemembered.split(",")) { - for (final Object o : AbilityUtils.getDefinedObjects(hostCard, rem, stAb)) { - if (o instanceof SpellAbility) { - // "RememberObjects$ Remembered" don't remember spellability - continue; - } + for (final Object o : AbilityUtils.getDefinedEntities(hostCard, rem, stAb)) { actualTrigger.addRemembered(o); } } @@ -895,10 +895,11 @@ public final class StaticAbilityContinuous { } // add Types - if ((addTypes != null) || (removeTypes != null)) { - affectedCard.addChangedCardTypes(addTypes, removeTypes, removeSuperTypes, removeCardTypes, - removeSubTypes, removeLandTypes, removeCreatureTypes, removeArtifactTypes, - removeEnchantmentTypes, hostCard.getTimestamp(), stAb.getId(), true, stAb.hasParam("CharacteristicDefining")); + if ((addTypes != null) || (removeTypes != null) || addAllCreatureTypes + || removeSuperTypes || removeCardTypes || removeLandTypes || removeCreatureTypes || removeArtifactTypes || removeEnchantmentTypes) { + affectedCard.addChangedCardTypes(addTypes, removeTypes, addAllCreatureTypes, removeSuperTypes, removeCardTypes, removeSubTypes, + removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes, + hostCard.getTimestamp(), stAb.getId(), true, stAb.hasParam("CharacteristicDefining")); } // add colors diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityUnspentMana.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityUnspentMana.java new file mode 100644 index 00000000000..f8896db7769 --- /dev/null +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityUnspentMana.java @@ -0,0 +1,45 @@ +package forge.game.staticability; + +import java.util.Collection; +import java.util.Set; + +import com.google.common.collect.Sets; + +import forge.card.MagicColor; +import forge.card.mana.ManaAtom; +import forge.game.Game; +import forge.game.card.Card; +import forge.game.player.Player; +import forge.game.zone.ZoneType; + +public class StaticAbilityUnspentMana { + + static String MODE = "UnspentMana"; + + public static Collection getManaToKeep(final Player player) { + final Game game = player.getGame(); + Set result = Sets.newHashSet(); + for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { + for (final StaticAbility stAb : ca.getStaticAbilities()) { + if (!stAb.getParam("Mode").equals(MODE) || stAb.isSuppressed() || !stAb.checkConditions()) { + continue; + } + applyUnspentManaAbility(stAb, player, result); + } + } + return result; + } + + public static void applyUnspentManaAbility(final StaticAbility stAb, final Player player, Set result) { + if (!stAb.matchesValidParam("ValidPlayer", player)) { + return; + } + if (!stAb.hasParam("ManaType")) { + for (byte b : ManaAtom.MANATYPES) { + result.add(b); + } + } else { + result.add(MagicColor.fromName(stAb.getParam("ManaType"))); + } + } +} diff --git a/forge-game/src/main/java/forge/game/trigger/Trigger.java b/forge-game/src/main/java/forge/game/trigger/Trigger.java index 69f890be854..713da987d6a 100644 --- a/forge-game/src/main/java/forge/game/trigger/Trigger.java +++ b/forge-game/src/main/java/forge/game/trigger/Trigger.java @@ -130,7 +130,6 @@ public abstract class Trigger extends TriggerReplacementBase { public String toString(boolean active) { if (hasParam("TriggerDescription") && !this.isSuppressed()) { - StringBuilder sb = new StringBuilder(); String currentName; if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) { diff --git a/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java b/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java index 1460f9f175e..277fd56868c 100644 --- a/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java +++ b/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java @@ -221,7 +221,7 @@ public class WrappedAbility extends Ability { public String toUnsuppressedString() { String desc = this.getStackDescription(); /* use augmented stack description as string for wrapped things */ String card = getHostCard().toString(); - if ( !desc.contains(card) && desc.contains(" this ")) { /* a hack for Evolve and similar that don't have CARDNAME */ + if (!desc.contains(card) && desc.contains(" this ")) { /* a hack for Evolve and similar that don't have CARDNAME */ return card + ": " + desc; } else return desc; } diff --git a/forge-game/src/main/java/forge/game/zone/PlayerZone.java b/forge-game/src/main/java/forge/game/zone/PlayerZone.java index 160042f0bed..ab52d23fee0 100644 --- a/forge-game/src/main/java/forge/game/zone/PlayerZone.java +++ b/forge-game/src/main/java/forge/game/zone/PlayerZone.java @@ -56,7 +56,7 @@ public class PlayerZone extends Zone { return true; } - if (c.isLand() && (!c.mayPlay(c.getController()).isEmpty())) { + if (c.isLand() && !c.mayPlay(c.getController()).isEmpty()) { return true; } diff --git a/forge-game/src/main/java/forge/game/zone/PlayerZoneBattlefield.java b/forge-game/src/main/java/forge/game/zone/PlayerZoneBattlefield.java index 8f6890555b5..8d361f92fe6 100644 --- a/forge-game/src/main/java/forge/game/zone/PlayerZoneBattlefield.java +++ b/forge-game/src/main/java/forge/game/zone/PlayerZoneBattlefield.java @@ -52,7 +52,6 @@ public class PlayerZoneBattlefield extends PlayerZone { meldedCards.remove(c); } - /** {@inheritDoc} */ @Override public final void add(final Card c, final Integer position, final Card latestState) { diff --git a/forge-game/src/main/java/forge/game/zone/Zone.java b/forge-game/src/main/java/forge/game/zone/Zone.java index b7446cb7d15..a380f6b8b1a 100644 --- a/forge-game/src/main/java/forge/game/zone/Zone.java +++ b/forge-game/src/main/java/forge/game/zone/Zone.java @@ -81,11 +81,9 @@ public class Zone implements java.io.Serializable, Iterable { public final void add(final Card c) { add(c, null); } - public final void add(final Card c, final Integer index) { add(c, index, null); } - public void add(final Card c, Integer index, final Card latestState) { if (index != null && cardList.isEmpty() && index.intValue() > 0) { // something went wrong, most likely the method fired when the game was in an unexpected state diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java b/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java index cc8903b14f9..0aaa4ba989c 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java @@ -11,11 +11,7 @@ import java.util.Collections; import java.util.List; import java.util.Vector; -import javax.swing.JButton; -import javax.swing.JPanel; -import javax.swing.ListSelectionModel; -import javax.swing.ScrollPaneConstants; -import javax.swing.SwingConstants; +import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; @@ -84,6 +80,8 @@ public class VLobby implements ILobbyView { private final StartButton btnStart = new StartButton(); private final JPanel pnlStart = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); + private final JComboBox gamesInMatch = new JComboBox(new String[] {"1","3","5"}); + private final JPanel gamesInMatchFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); private final JPanel constructedFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); // Main content frame // Variants frame and variables @@ -212,11 +210,19 @@ public class VLobby implements ILobbyView { public final void actionPerformed(final ActionEvent arg0) { Runnable startGame = lobby.startGame(); if (startGame != null) { + if (!gamesInMatch.getSelectedItem().equals(ForgePreferences.FPref.UI_MATCHES_PER_GAME)) { + FModel.getPreferences().setPref(FPref.UI_MATCHES_PER_GAME, (String) gamesInMatch.getSelectedItem()); + } startGame.run(); } } }); } + gamesInMatchFrame.add(newLabel(localizer.getMessage("lblGamesInMatch")), "w 150px!, h 30px!"); + gamesInMatchFrame.add(gamesInMatch, "w 50px!, h 30px!"); + gamesInMatchFrame.setOpaque(false); + gamesInMatch.setSelectedItem("3"); + pnlStart.add(gamesInMatchFrame); } public void updateDeckPanel() { diff --git a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java index 54d7c376fba..86a63f6ceee 100644 --- a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java +++ b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulatorTest.java @@ -48,7 +48,7 @@ public class GameSimulatorTest extends SimulationTestCase { assertEquals(1, heraldCopy.getToughnessBonusFromCounters()); assertEquals(1, heraldCopy.getPowerBonusFromCounters()); - Card warriorToken = findCardWithName(simGame, "Warrior"); + Card warriorToken = findCardWithName(simGame, "Warrior Token"); assertNotNull(warriorToken); assertTrue(warriorToken.isSick()); assertEquals(1, warriorToken.getCurrentPower()); @@ -233,7 +233,7 @@ public class GameSimulatorTest extends SimulationTestCase { GameSimulator sim = createSimulator(game, p); sim.simulateSpellAbility(minusTwo); Game simGame = sim.getSimulatedGameState(); - Card vampireToken = findCardWithName(simGame, "Vampire"); + Card vampireToken = findCardWithName(simGame, "Vampire Token"); assertNotNull(vampireToken); Player simP = simGame.getPlayers().get(1); @@ -599,7 +599,7 @@ public class GameSimulatorTest extends SimulationTestCase { assertTrue(score > 0); Game simGame = sim.getSimulatedGameState(); - Card scion = findCardWithName(simGame, "Eldrazi Scion"); + Card scion = findCardWithName(simGame, "Eldrazi Scion Token"); assertNotNull(scion); assertEquals(1, scion.getNetPower()); assertEquals(1, scion.getNetToughness()); @@ -608,7 +608,7 @@ public class GameSimulatorTest extends SimulationTestCase { GameCopier copier = new GameCopier(simGame); Game copy = copier.makeCopy(); - Card scionCopy = findCardWithName(copy, "Eldrazi Scion"); + Card scionCopy = findCardWithName(copy, "Eldrazi Scion Token"); assertNotNull(scionCopy); assertEquals(1, scionCopy.getNetPower()); assertEquals(1, scionCopy.getNetToughness()); @@ -1288,7 +1288,7 @@ public class GameSimulatorTest extends SimulationTestCase { assertTrue(score > 0); Game simGame = sim.getSimulatedGameState(); - int numZombies = countCardsWithName(simGame, "Zombie"); + int numZombies = countCardsWithName(simGame, "Zombie Token"); assertEquals(2, numZombies); } @@ -1323,11 +1323,11 @@ public class GameSimulatorTest extends SimulationTestCase { GameSimulator sim = createSimulator(game, p); int score = sim.simulateSpellAbility(fatalPushSA).value; assertTrue(score > 0); - assertEquals(2, countCardsWithName(sim.getSimulatedGameState(), "Zombie")); + assertEquals(2, countCardsWithName(sim.getSimulatedGameState(), "Zombie Token")); score = sim.simulateSpellAbility(electrifySA).value; assertTrue(score > 0); - assertEquals(countCardsWithName(sim.getSimulatedGameState(), "Zombie"), 4); + assertEquals(4, countCardsWithName(sim.getSimulatedGameState(), "Zombie Token")); } public void testPlayerXCount() { @@ -1564,7 +1564,7 @@ public class GameSimulatorTest extends SimulationTestCase { assertTrue(score > 0); Game simGame = sim.getSimulatedGameState(); - int numZombies = countCardsWithName(simGame, "Zombie"); + int numZombies = countCardsWithName(simGame, "Zombie Token"); assertEquals(4, numZombies); } @@ -1592,7 +1592,7 @@ public class GameSimulatorTest extends SimulationTestCase { assertTrue(score > 0); Game simGame = sim.getSimulatedGameState(); - int numZombies = countCardsWithName(simGame, "Zombie"); + int numZombies = countCardsWithName(simGame, "Zombie Token"); assertEquals(3, numZombies); } diff --git a/forge-gui-desktop/src/test/java/forge/card/CardDbTestCase.java b/forge-gui-desktop/src/test/java/forge/card/CardDbTestCase.java index 503e5ba46b7..6c0cf5d013c 100644 --- a/forge-gui-desktop/src/test/java/forge/card/CardDbTestCase.java +++ b/forge-gui-desktop/src/test/java/forge/card/CardDbTestCase.java @@ -2101,7 +2101,7 @@ public class CardDbTestCase extends ForgeCardMockTestCase { @Test public void testMaxArtCountForBasicLand(){ int maxArtIndex = this.cardDb.getMaxArtIndex("Island"); - assertEquals(maxArtIndex, 13); + assertTrue(maxArtIndex >= 14); } @Test diff --git a/forge-gui-mobile/src/forge/deck/FDeckEditor.java b/forge-gui-mobile/src/forge/deck/FDeckEditor.java index 6e11ea051ca..04e97b50be8 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckEditor.java +++ b/forge-gui-mobile/src/forge/deck/FDeckEditor.java @@ -16,6 +16,7 @@ import forge.deck.io.DeckPreferences; import forge.gamemodes.limited.BoosterDraft; import forge.gamemodes.planarconquest.ConquestUtil; import forge.gui.FThreads; +import forge.gui.GuiBase; import forge.gui.card.CardPreferences; import forge.item.PaperCard; import forge.itemmanager.CardManager; @@ -768,7 +769,10 @@ public class FDeckEditor extends TabPageScreen { } protected void initialize() { - cardManager.setup(config); + if (GuiBase.isAdventureMode()) + cardManager.setup(config); + else //fix planar conquest deck editor and maybe others... + cardManager.setup(config, parentScreen.getColOverrides(config)); } protected boolean canAddCards() { diff --git a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java index 82195fb2593..7350f457952 100644 --- a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java +++ b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java @@ -70,6 +70,10 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { private final FLabel lblVariants = new FLabel.Builder().text(localizer.getMessage("lblVariants") + ":").font(VARIANTS_FONT).build(); private final FComboBox cbVariants = new FComboBox<>(); + // Max games in a match frame and variables + private final FLabel lblGamesInMatch = new FLabel.Builder().text(localizer.getMessage("lblMatch") + ":").font(VARIANTS_FONT).build(); + private final FComboBox cbGamesInMatch = new FComboBox<>(); + private final List playerPanels = new ArrayList<>(MAX_PLAYERS); private final FScrollPane playersScroll = new FScrollPane() { @Override @@ -127,6 +131,20 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { initLobby(lobby0); + add(lblGamesInMatch); + add(cbGamesInMatch); + cbGamesInMatch.setFont(VARIANTS_FONT); + cbGamesInMatch.addItem("1"); + cbGamesInMatch.addItem("3"); + cbGamesInMatch.addItem("5"); + cbGamesInMatch.setSelectedItem(FModel.getPreferences().getPref((FPref.UI_MATCHES_PER_GAME))); + cbGamesInMatch.setChangedHandler(new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + FModel.getPreferences().setPref(FPref.UI_MATCHES_PER_GAME, cbGamesInMatch.getSelectedItem()); + } + }); + add(lblVariants); add(cbVariants); cbVariants.setFont(VARIANTS_FONT); @@ -207,6 +225,8 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { btnStart.setEnabled(hasControl); lblVariants.setEnabled(hasControl); cbVariants.setEnabled(hasControl); + lblGamesInMatch.setEnabled(hasControl); + cbGamesInMatch.setEnabled(hasControl); lblPlayers.setEnabled(hasControl); cbPlayerCount.setEnabled(hasControl); while (lobby.getNumberOfSlots() < getNumPlayers()){ @@ -255,19 +275,29 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { if (Forge.isLandscapeMode()) { lblVariants.setBounds(x, y, lblVariants.getAutoSizeBounds().width + PADDING / 2, fieldHeight); x += lblVariants.getWidth(); - cbVariants.setBounds(x, y, width - (x + lblPlayers.getAutoSizeBounds().width + PADDING/2 + Utils.AVG_FINGER_WIDTH + PADDING), fieldHeight); + cbVariants.setBounds(x, y, width - (x + lblGamesInMatch.getAutoSizeBounds().width + PADDING/2 + + lblPlayers.getAutoSizeBounds().width + (Utils.AVG_FINGER_WIDTH + PADDING)*2), fieldHeight); x += cbVariants.getWidth(); lblPlayers.setBounds(x, y, lblPlayers.getAutoSizeBounds().width + PADDING / 2, fieldHeight); x += lblPlayers.getWidth(); cbPlayerCount.setBounds(x, y, Utils.AVG_FINGER_WIDTH, fieldHeight); + x += cbPlayerCount.getWidth() + PADDING; + lblGamesInMatch.setBounds(x, y, lblGamesInMatch.getAutoSizeBounds().width + PADDING / 2, fieldHeight); + x += lblGamesInMatch.getWidth(); + cbGamesInMatch.setBounds(x, y, Utils.AVG_FINGER_WIDTH, fieldHeight); } else { + lblVariants.setBounds(x, y, lblVariants.getAutoSizeBounds().width + PADDING / 2, fieldHeight); + x += lblVariants.getWidth(); + cbVariants.setBounds(x, y, width - x - PADDING, fieldHeight); + x = PADDING; + y += cbVariants.getHeight() + PADDING; lblPlayers.setBounds(x, y, lblPlayers.getAutoSizeBounds().width + PADDING / 2, fieldHeight); x += lblPlayers.getWidth(); cbPlayerCount.setBounds(x, y, Utils.AVG_FINGER_WIDTH, fieldHeight); x += cbPlayerCount.getWidth() + PADDING; - lblVariants.setBounds(x, y, lblVariants.getAutoSizeBounds().width + PADDING / 2, fieldHeight); - x += lblVariants.getWidth(); - cbVariants.setBounds(x, y, width - x - PADDING, fieldHeight); + lblGamesInMatch.setBounds(x, y, lblGamesInMatch.getAutoSizeBounds().width + PADDING / 2, fieldHeight); + x += lblGamesInMatch.getWidth(); + cbGamesInMatch.setBounds(x, y, Utils.AVG_FINGER_WIDTH, fieldHeight); } y += cbPlayerCount.getHeight() + PADDING; playersScroll.setBounds(0, y, width, height - y); diff --git a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java index f1d95059f78..e63a7c8acd9 100644 --- a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java +++ b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java @@ -518,10 +518,14 @@ public class FChoiceList extends FList implements ActivateHandler { @Override public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) { //should fix NPE ie Thief of Sanity, Gonti... etc - CardView cv = ((IHasCardView)value).getCardView(); - if (cv != null) { - boolean showAlternate = showAlternate(cv, value.toString()); - CardRenderer.drawCardWithOverlays(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true); + try { + CardView cv = ((IHasCardView) value).getCardView(); + if (cv != null) { + boolean showAlternate = showAlternate(cv, value.toString()); + CardRenderer.drawCardWithOverlays(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true); + } + } catch (Exception e) { + //fixme: java.lang.ClassCastException for cards like Subtlety which should be cancelable instead... } float dx = VStack.CARD_WIDTH + FList.PADDING; diff --git a/forge-gui/res/cardsfolder/a/abeyance.txt b/forge-gui/res/cardsfolder/a/abeyance.txt index b0fd91aa561..7ed01a2ac3d 100644 --- a/forge-gui/res/cardsfolder/a/abeyance.txt +++ b/forge-gui/res/cardsfolder/a/abeyance.txt @@ -3,7 +3,7 @@ ManaCost:1 W Types:Instant A:SP$ Effect | Cost$ 1 W | ValidTgts$ Player | Name$ Abeyance Effect | StaticAbilities$ STCantBeCast,STCantBeActivated | RememberObjects$ Targeted | AILogic$ BeginningOfOppTurn | SubAbility$ DBDraw | SpellDescription$ Until end of turn, target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities. SVar:STCantBeCast:Mode$ CantBeCast | ValidCard$ Instant,Sorcery | Caster$ Player.IsRemembered | EffectZone$ Command | Description$ Target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities. -SVar:STCantBeActivated:Mode$ CantBeActivated | ValidCard$ Card | Activator$ Player.IsRemembered | EffectZone$ Command | NonMana$ True +SVar:STCantBeActivated:Mode$ CantBeActivated | ValidCard$ Card | ValidSA$ Activated.nonManaAbility | Activator$ Player.IsRemembered | EffectZone$ Command SVar:DBDraw:DB$ Draw | NumCards$ 1 | SpellDescription$ Draw a card. SVar:Picture:http://www.wizards.com/global/images/magic/general/abeyance.jpg Oracle:Until end of turn, target player can't cast instant or sorcery spells, and that player can't activate abilities that aren't mana abilities.\nDraw a card. diff --git a/forge-gui/res/cardsfolder/a/acidic_dagger.txt b/forge-gui/res/cardsfolder/a/acidic_dagger.txt index 56ab0a7339b..018f56d5ba0 100644 --- a/forge-gui/res/cardsfolder/a/acidic_dagger.txt +++ b/forge-gui/res/cardsfolder/a/acidic_dagger.txt @@ -1,7 +1,7 @@ Name:Acidic Dagger ManaCost:4 Types:Artifact -A:AB$ Effect | Cost$ 4 T | Name$ Acidic Dagger Effect | ValidTgts$ Creature | TgtPrompt$ Select target creature | Triggers$ TrigDam,TrigLeave | RememberObjects$ Targeted | ImprintCards$ Self | ActivationPhases$ Upkeep->Declare Attackers | SpellDescription$ Whenever target creature deals combat damage to a non-Wall creature this turn, destroy that non-Wall creature. When the targeted creature leaves the battlefield this turn, sacrifice CARDNAME. Activate only before blockers are declared. +A:AB$ Effect | Cost$ 4 T | Name$ Acidic Dagger Effect | ValidTgts$ Creature | TgtPrompt$ Select target creature | Triggers$ TrigDam,TrigLeave | RememberObjects$ Targeted | ImprintCards$ Self | ActivationPhases$ Upkeep->Declare Attackers | ActivationFirstCombat$ True | SpellDescription$ Whenever target creature deals combat damage to a non-Wall creature this turn, destroy that non-Wall creature. When the targeted creature leaves the battlefield this turn, sacrifice CARDNAME. Activate only before blockers are declared. SVar:TrigDam:Mode$ DamageDone | ValidSource$ Creature.IsRemembered | ValidTarget$ Creature.nonWall | CombatDamage$ True | TriggerZones$ Command | Execute$ TrigDestroy | TriggerDescription$ Whenever targeted creature deals combat damage to a non-Wall creature this turn, destroy that non-Wall creature. SVar:TrigLeave:Mode$ ChangesZone | ValidCard$ Creature.IsRemembered | Origin$ Battlefield | Destination$ Any | Execute$ TrigSac | TriggerZones$ Command | TriggerDescription$ When the targeted creature leaves the battlefield this turn, sacrifice Acidic Dagger. SVar:TrigDestroy:DB$ Destroy | Defined$ TriggeredTargetLKICopy diff --git a/forge-gui/res/cardsfolder/a/amoeboid_changeling.txt b/forge-gui/res/cardsfolder/a/amoeboid_changeling.txt index ccff951ec48..ce57c35f97c 100644 --- a/forge-gui/res/cardsfolder/a/amoeboid_changeling.txt +++ b/forge-gui/res/cardsfolder/a/amoeboid_changeling.txt @@ -3,7 +3,7 @@ ManaCost:1 U Types:Creature Shapeshifter PT:1/1 K:Changeling -A:AB$ Animate | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | Types$ AllCreatureTypes | SpellDescription$ Target creature gains all creature types until end of turn. +A:AB$ Animate | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | AddAllCreatureTypes$ True | SpellDescription$ Target creature gains all creature types until end of turn. A:AB$ Animate | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | Types$ Creature | RemoveCreatureTypes$ True | IsCurse$ True | SpellDescription$ Target creature loses all creature types until end of turn. AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/amoeboid_changeling.jpg diff --git a/forge-gui/res/cardsfolder/a/amorphous_axe.txt b/forge-gui/res/cardsfolder/a/amorphous_axe.txt index 78ddc289f81..4124a095db8 100644 --- a/forge-gui/res/cardsfolder/a/amorphous_axe.txt +++ b/forge-gui/res/cardsfolder/a/amorphous_axe.txt @@ -1,6 +1,6 @@ Name:Amorphous Axe ManaCost:2 Types:Artifact Equipment -S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 3 | AddType$ AllCreatureTypes | Description$ Equipped creature gets +3/+0 and is every creature type. +S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 3 | AddAllCreatureTypes$ True | Description$ Equipped creature gets +3/+0 and is every creature type. K:Equip:3 Oracle:Equipped creature gets +3/+0 and is every creature type.\nEquip {3} ({3}: Attach to target creature you control. Equip only as a sorcery.) diff --git a/forge-gui/res/cardsfolder/a/angus_mackenzie.txt b/forge-gui/res/cardsfolder/a/angus_mackenzie.txt index 9806244857b..2e2133b94ab 100644 --- a/forge-gui/res/cardsfolder/a/angus_mackenzie.txt +++ b/forge-gui/res/cardsfolder/a/angus_mackenzie.txt @@ -2,7 +2,7 @@ Name:Angus Mackenzie ManaCost:G W U Types:Legendary Creature Human Cleric PT:2/2 -A:AB$ Fog | Cost$ G W U T | ActivationPhases$ Upkeep->Declare Blockers | SpellDescription$ Prevent all combat damage that would be dealt this turn. Activate only before the combat damage step. +A:AB$ Fog | Cost$ G W U T | ActivationPhases$ Upkeep->Declare Blockers | ActivationFirstCombat$ True | SpellDescription$ Prevent all combat damage that would be dealt this turn. Activate only before the combat damage step. SVar:NonCombatPriority:2 SVar:Picture:http://www.wizards.com/global/images/magic/general/angus_mackenzie.jpg Oracle:{G}{W}{U}, {T}: Prevent all combat damage that would be dealt this turn. Activate only before the combat damage step. diff --git a/forge-gui/res/cardsfolder/a/animation_module.txt b/forge-gui/res/cardsfolder/a/animation_module.txt index 6744d3d0a37..9dcfa071aab 100644 --- a/forge-gui/res/cardsfolder/a/animation_module.txt +++ b/forge-gui/res/cardsfolder/a/animation_module.txt @@ -3,7 +3,7 @@ ManaCost:1 Types:Artifact T:Mode$ CounterAddedOnce | ValidCard$ Permanent.YouCtrl | TriggerZones$ Battlefield | CounterType$ P1P1 | Execute$ TrigToken | TriggerDescription$ Whenever one or more +1/+1 counters are put on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token. SVar:TrigToken:AB$ Token | Cost$ 1 | TokenAmount$ 1 | TokenScript$ c_1_1_a_servo | TokenOwner$ You | LegacyImage$ c 1 1 a servo kld -A:AB$ PutCounter | Cost$ 3 T | ValidTgts$ Permanent,Player | TgtPrompt$ Select target player or permanent | CounterType$ ExistingCounter | CounterNum$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Choose a counter on target permanent or player. Give that permanent or player another counter of that kind. +A:AB$ PutCounter | Cost$ 3 T | ValidTgts$ Permanent,Player | TgtPrompt$ Select target player or permanent | CounterType$ ExistingCounter | CounterNum$ 1 | AILogic$ AtOppEOT | SpellDescription$ Choose a counter on target permanent or player. Give that permanent or player another counter of that kind. DeckHints:Ability$Counters AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/animation_module.jpg diff --git a/forge-gui/res/cardsfolder/a/arachnoform.txt b/forge-gui/res/cardsfolder/a/arachnoform.txt index 320d7fdc023..d77ab88e0a2 100644 --- a/forge-gui/res/cardsfolder/a/arachnoform.txt +++ b/forge-gui/res/cardsfolder/a/arachnoform.txt @@ -3,5 +3,5 @@ ManaCost:1 G Types:Enchantment Aura K:Enchant creature A:SP$ Attach | Cost$ 1 G | ValidTgts$ Creature | AILogic$ Pump -S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 2 | AddToughness$ 2 | AddKeyword$ Reach | AddType$ AllCreatureTypes | Description$ Enchanted creature gets +2/+2, has reach, and is every creature type. +S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 2 | AddToughness$ 2 | AddKeyword$ Reach | AddAllCreatureTypes$ True | Description$ Enchanted creature gets +2/+2, has reach, and is every creature type. Oracle:Enchant creature\nEnchanted creature gets +2/+2, has reach, and is every creature type. diff --git a/forge-gui/res/cardsfolder/a/arch_of_orazca.txt b/forge-gui/res/cardsfolder/a/arch_of_orazca.txt index c27560e1810..cdf8f8cf6a4 100644 --- a/forge-gui/res/cardsfolder/a/arch_of_orazca.txt +++ b/forge-gui/res/cardsfolder/a/arch_of_orazca.txt @@ -3,6 +3,6 @@ ManaCost:no cost Types:Land K:Ascend A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. -A:AB$ Draw | Cost$ 5 T | NumCards$ 1 | Activation$ Blessing | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. Activate only if you have the city's blessing. +A:AB$ Draw | Cost$ 5 T | NumCards$ 1 | Activation$ Blessing | AILogic$ AtOppEOT | SpellDescription$ Draw a card. Activate only if you have the city's blessing. SVar:Picture:http://www.wizards.com/global/images/magic/general/arch_of_orazca.jpg Oracle:Ascend (If you control ten or more permanents, you get the city's blessing for the rest of the game.)\n{T}: Add {C}.\n{5}, {T}: Draw a card. Activate only if you have the city's blessing. diff --git a/forge-gui/res/cardsfolder/a/archfiend_of_despair.txt b/forge-gui/res/cardsfolder/a/archfiend_of_despair.txt index eba83fa0fbc..8cdc2680e97 100644 --- a/forge-gui/res/cardsfolder/a/archfiend_of_despair.txt +++ b/forge-gui/res/cardsfolder/a/archfiend_of_despair.txt @@ -3,7 +3,7 @@ ManaCost:6 B B Types:Creature Demon PT:6/6 K:Flying -S:Mode$ Continuous | Affected$ Player.Opponent | AddKeyword$ You can't gain life. | Description$ Your opponents can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Player.Opponent | Description$ Your opponents can't gain life. T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | Execute$ RepeatOpps | TriggerDescription$ At the beginning of each end step, each opponent loses life equal to the life they lost this turn. (Damage causes loss of life.) SVar:RepeatOpps:DB$ RepeatEach | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ TrigLoseLife SVar:TrigLoseLife:DB$ LoseLife | Defined$ Remembered | LifeAmount$ X diff --git a/forge-gui/res/cardsfolder/a/arcums_whistle.txt b/forge-gui/res/cardsfolder/a/arcums_whistle.txt index 19c604eb50c..0dcdecd6373 100644 --- a/forge-gui/res/cardsfolder/a/arcums_whistle.txt +++ b/forge-gui/res/cardsfolder/a/arcums_whistle.txt @@ -1,7 +1,7 @@ Name:Arcum's Whistle ManaCost:3 Types:Artifact -A:AB$ Pump | Cost$ 3 T | ActivationPhases$ Upkeep->BeginCombat | ValidTgts$ Creature.nonWall+ActivePlayerCtrl+notFirstTurnControlled | TgtPrompt$ Select target non-Wall creature the active player has controlled continuously since the beginning of the turn. | IsCurse$ True | KW$ HIDDEN CARDNAME attacks each combat if able. | UnlessCost$ X | UnlessPayer$ TargetedController | UnlessResolveSubs$ WhenNotPaid | SubAbility$ DestroyPacifist | SpellDescription$ Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That player may pay {X}, where X is that creature's mana value. If they don't pay, the creature attacks this turn if able, and at the beginning of the next end step, destroy it if it didn't attack this turn. Activate only before attackers are declared. +A:AB$ Pump | Cost$ 3 T | ActivationPhases$ Upkeep->BeginCombat | ActivationFirstCombat$ True | ValidTgts$ Creature.nonWall+ActivePlayerCtrl+notFirstTurnControlled | TgtPrompt$ Select target non-Wall creature the active player has controlled continuously since the beginning of the turn. | IsCurse$ True | KW$ HIDDEN CARDNAME attacks each combat if able. | UnlessCost$ X | UnlessPayer$ TargetedController | UnlessResolveSubs$ WhenNotPaid | SubAbility$ DestroyPacifist | SpellDescription$ Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That player may pay {X}, where X is that creature's mana value. If they don't pay, the creature attacks this turn if able, and at the beginning of the next end step, destroy it if it didn't attack this turn. Activate only before attackers are declared. SVar:DestroyPacifist:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigDestroy | RememberObjects$ ParentTarget | TriggerDescription$ At the beginning of the end step, destroy that creature if it didn't attack this turn. SVar:TrigDestroy:DB$ Destroy | Defined$ DelayTriggerRemembered | ConditionDefined$ DelayTriggerRemembered | ConditionPresent$ Creature.notAttackedThisTurn | ConditionCompare$ GE1 SVar:X:Targeted$CardManaCost diff --git a/forge-gui/res/cardsfolder/a/atarkas_command.txt b/forge-gui/res/cardsfolder/a/atarkas_command.txt index b72da0adbf1..01a469f0388 100644 --- a/forge-gui/res/cardsfolder/a/atarkas_command.txt +++ b/forge-gui/res/cardsfolder/a/atarkas_command.txt @@ -3,9 +3,8 @@ ManaCost:R G Types:Instant A:SP$ Charm | Cost$ R G | Choices$ DBNoLife,DBDamage,DBLand,DBPumpAll | CharmNum$ 2 SVar:DBNoLife:DB$ Effect | Name$ Atarka's Command Effect | StaticAbilities$ STCantGain | AILogic$ NoGain | SpellDescription$ Your opponents can't gain life this turn. -SVar:STCantGain:Mode$ Continuous | EffectZone$ Command | Affected$ Player.Opponent | AddKeyword$ You can't gain life. | Description$ Your opponents can't gain life. +SVar:STCantGain:Mode$ CantGainLife | ValidPlayer$ Player.Opponent | Description$ Your opponents can't gain life this turn. SVar:DBDamage:DB$ DealDamage | Defined$ Player.Opponent | NumDmg$ 3 | AILogic$ Good | SpellDescription$ CARDNAME deals 3 damage to each opponent. SVar:DBLand:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Land | ChangeNum$ 1 | Optional$ You | SpellDescription$ You may put a land card from your hand onto the battlefield. SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature.YouCtrl | NumAtt$ +1 | NumDef$ +1 | KW$ Reach | SpellDescription$ Creatures you control get +1/+1 and gain reach until end of turn. -SVar:Picture:http://www.wizards.com/global/images/magic/general/atarkas_command.jpg Oracle:Choose two —\n• Your opponents can't gain life this turn.\n• Atarka's Command deals 3 damage to each opponent.\n• You may put a land card from your hand onto the battlefield.\n• Creatures you control get +1/+1 and gain reach until end of turn. diff --git a/forge-gui/res/cardsfolder/a/azami_lady_of_scrolls.txt b/forge-gui/res/cardsfolder/a/azami_lady_of_scrolls.txt index aa6f5c1997c..7c2235148cf 100644 --- a/forge-gui/res/cardsfolder/a/azami_lady_of_scrolls.txt +++ b/forge-gui/res/cardsfolder/a/azami_lady_of_scrolls.txt @@ -2,7 +2,7 @@ Name:Azami, Lady of Scrolls ManaCost:2 U U U Types:Legendary Creature Human Wizard PT:0/2 -A:AB$ Draw | Cost$ tapXType<1/Wizard> | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. +A:AB$ Draw | Cost$ tapXType<1/Wizard> | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card. AI:RemoveDeck:Random DeckHints:Type$Wizard SVar:Picture:http://www.wizards.com/global/images/magic/general/azami_lady_of_scrolls.jpg diff --git a/forge-gui/res/cardsfolder/b/basalt_monolith.txt b/forge-gui/res/cardsfolder/b/basalt_monolith.txt index c39850bf3d1..3ee57c69ff4 100644 --- a/forge-gui/res/cardsfolder/b/basalt_monolith.txt +++ b/forge-gui/res/cardsfolder/b/basalt_monolith.txt @@ -2,7 +2,7 @@ Name:Basalt Monolith ManaCost:3 Types:Artifact K:CARDNAME doesn't untap during your untap step. -A:AB$ Untap | Cost$ 3 | SpellDescription$ Untap CARDNAME. +A:AB$ Untap | Cost$ 3 | AILogic$ EOT | AIManaPref$ NotSameCard | SpellDescription$ Untap CARDNAME. A:AB$ Mana | Cost$ T | Produced$ C | Amount$ 3 | SpellDescription$ Add {C}{C}{C}. AI:RemoveDeck:Random SVar:Picture:http://www.wizards.com/global/images/magic/general/basalt_monolith.jpg diff --git a/forge-gui/res/cardsfolder/b/berserk.txt b/forge-gui/res/cardsfolder/b/berserk.txt index e879ab9a99f..613cf3afdd2 100644 --- a/forge-gui/res/cardsfolder/b/berserk.txt +++ b/forge-gui/res/cardsfolder/b/berserk.txt @@ -1,7 +1,7 @@ Name:Berserk ManaCost:G Types:Instant -A:SP$ Pump | Cost$ G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ X | KW$ Trample | ActivationPhases$ Upkeep->Declare Blockers | SubAbility$ DelTrig | AILogic$ Berserk | SpellDescription$ Cast CARDNAME only before the combat damage step. Target creature gains trample and gets +X/+0 until end of turn, where X is its power. At the beginning of the next end step, destroy that creature if it attacked this turn. +A:SP$ Pump | Cost$ G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ X | KW$ Trample | ActivationPhases$ Upkeep->Declare Blockers | ActivationFirstCombat$ True | SubAbility$ DelTrig | AILogic$ Berserk | SpellDescription$ Cast CARDNAME only before the combat damage step. Target creature gains trample and gets +X/+0 until end of turn, where X is its power. At the beginning of the next end step, destroy that creature if it attacked this turn. SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End Of Turn | Execute$ TrigDestroy | RememberObjects$ Targeted | TriggerDescription$ At the beginning of the next end step, destroy that creature if it attacked this turn. | AILogic$ Always SVar:TrigDestroy:DB$ Destroy | Defined$ DelayTriggerRemembered | ConditionDefined$ DelayTriggerRemembered | ConditionPresent$ Card.attackedThisTurn | ConditionCompare$ GE1 SVar:X:Targeted$CardPower diff --git a/forge-gui/res/cardsfolder/b/blades_of_velis_vel.txt b/forge-gui/res/cardsfolder/b/blades_of_velis_vel.txt index c95779cbfc4..528c1228ac3 100644 --- a/forge-gui/res/cardsfolder/b/blades_of_velis_vel.txt +++ b/forge-gui/res/cardsfolder/b/blades_of_velis_vel.txt @@ -3,6 +3,6 @@ ManaCost:1 R Types:Tribal Instant Shapeshifter K:Changeling A:SP$ Pump | Cost$ 1 R | TargetMin$ 0 | TargetMax$ 2 | NumAtt$ +2 | ValidTgts$ Creature | TgtPrompt$ Select target Creature | SubAbility$ DBAnimate | SpellDescription$ Up to two target creatures each get +2/+0 and gain all creature types until end of turn. -SVar:DBAnimate:DB$ Animate | Defined$ Targeted | Types$ AllCreatureTypes +SVar:DBAnimate:DB$ Animate | Defined$ Targeted | AddAllCreatureTypes$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/blades_of_velis_vel.jpg Oracle:Changeling (This card is every creature type.)\nUp to two target creatures each get +2/+0 and gain all creature types until end of turn. diff --git a/forge-gui/res/cardsfolder/b/blood_frenzy.txt b/forge-gui/res/cardsfolder/b/blood_frenzy.txt index 3f1e2b3df0c..99a2934e41c 100644 --- a/forge-gui/res/cardsfolder/b/blood_frenzy.txt +++ b/forge-gui/res/cardsfolder/b/blood_frenzy.txt @@ -1,6 +1,6 @@ Name:Blood Frenzy ManaCost:1 R Types:Instant -A:SP$ Pump | Cost$ 1 R | ActivationPhases$ Upkeep,Draw,Main1,BeginCombat,Declare Attackers,Declare Blockers | ValidTgts$ Creature.attacking,Creature.blocking | TgtPrompt$ Select target attacking or blocking creature | NumAtt$ +4 | NumDef$ +0 | AtEOT$ Destroy | SpellDescription$ Cast CARDNAME only before the combat damage step. Target attacking or blocking creature gets +4/+0 until end of turn. Destroy that creature at the beginning of the next end step. +A:SP$ Pump | Cost$ 1 R | ActivationPhases$ Upkeep->Declare Blockers | ActivationFirstCombat$ True | ValidTgts$ Creature.attacking,Creature.blocking | TgtPrompt$ Select target attacking or blocking creature | NumAtt$ +4 | NumDef$ +0 | AtEOT$ Destroy | SpellDescription$ Cast CARDNAME only before the combat damage step. Target attacking or blocking creature gets +4/+0 until end of turn. Destroy that creature at the beginning of the next end step. SVar:Picture:http://www.wizards.com/global/images/magic/general/blood_frenzy.jpg Oracle:Cast this spell only before the combat damage step.\nTarget attacking or blocking creature gets +4/+0 until end of turn. Destroy that creature at the beginning of the next end step. diff --git a/forge-gui/res/cardsfolder/b/bound_in_gold.txt b/forge-gui/res/cardsfolder/b/bound_in_gold.txt index 5f526e7b244..10cb5a90df9 100644 --- a/forge-gui/res/cardsfolder/b/bound_in_gold.txt +++ b/forge-gui/res/cardsfolder/b/bound_in_gold.txt @@ -4,5 +4,5 @@ Types:Enchantment Aura K:Enchant permanent A:SP$ Attach | Cost$ 2 W | ValidTgts$ Permanent | AILogic$ Curse S:Mode$ Continuous | Affected$ Permanent.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block. & CARDNAME can't crew Vehicles. | Description$ Enchanted permanent can't attack, block, or crew Vehicles, and its activated abilities can't be activated unless they're mana abilities. -S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | NonMana$ True +S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | ValidSA$ Activated.nonManaAbility Oracle:Enchant permanent\nEnchanted permanent can't attack, block, or crew Vehicles, and its activated abilities can't be activated unless they're mana abilities. diff --git a/forge-gui/res/cardsfolder/c/carth_the_lion.txt b/forge-gui/res/cardsfolder/c/carth_the_lion.txt index 10c51aa5ff1..98864070182 100644 --- a/forge-gui/res/cardsfolder/c/carth_the_lion.txt +++ b/forge-gui/res/cardsfolder/c/carth_the_lion.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Human Warrior PT:3/5 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ Whenever CARDNAME enters the battlefield or a planeswalker you control dies, look at the top seven cards of your library. You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Planeswalker.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDig | Secondary$ True | TriggerDescription$ Whenever CARDNAME enters the battlefield or a planeswalker you control dies, look at the top seven cards of your library. You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. -SVar:TrigDig:DB$ Dig | DigNum$ 7 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Planeswalker | RestRandomOrder$ True | Reveal$ True +SVar:TrigDig:DB$ Dig | DigNum$ 7 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Planeswalker | RestRandomOrder$ True | ForceRevealToController$ True S:Mode$ RaiseCost | ValidCard$ Planeswalker.YouCtrl | Type$ Loyalty | Cost$ AddCounter<1/LOYALTY> | Description$ Planeswalkers' loyalty abilities you activate cost an additional [+1] to activate. DeckNeeds:Type$Planeswalker Oracle:Whenever Carth the Lion enters the battlefield or a planeswalker you control dies, look at the top seven cards of your library. You may reveal a planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.\nPlaneswalkers' loyalty abilities you activate cost an additional [+1] to activate. diff --git a/forge-gui/res/cardsfolder/c/cast_out.txt b/forge-gui/res/cardsfolder/c/cast_out.txt index 11266256ed5..ddff71a35fe 100644 --- a/forge-gui/res/cardsfolder/c/cast_out.txt +++ b/forge-gui/res/cardsfolder/c/cast_out.txt @@ -3,7 +3,7 @@ ManaCost:3 W Types:Enchantment K:Flash T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, exile target nonland permanent an opponent controls until CARDNAME leaves the battlefield. -SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Permanent.nonLand+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls | Duration$ UntilHostLeavesPlay +SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Permanent.nonLand+OppCtrl | TgtPrompt$ Select target nonland permanent an opponent controls | Duration$ UntilHostLeavesPlay K:Cycling:W SVar:OblivionRing:TRUE Oracle:Flash\nWhen Cast Out enters the battlefield, exile target nonland permanent an opponent controls until Cast Out leaves the battlefield.\nCycling {W} ({W}, Discard this card: Draw a card.) diff --git a/forge-gui/res/cardsfolder/c/castle_locthwain.txt b/forge-gui/res/cardsfolder/c/castle_locthwain.txt index ed3e4ca50e1..749b6fa7144 100644 --- a/forge-gui/res/cardsfolder/c/castle_locthwain.txt +++ b/forge-gui/res/cardsfolder/c/castle_locthwain.txt @@ -4,7 +4,7 @@ Types:Land K:ETBReplacement:Other:LandTapped SVar:LandTapped:DB$ Tap | Defined$ Self | ETB$ True | ConditionPresent$ Swamp.YouCtrl | ConditionCompare$ EQ0 | SpellDescription$ CARDNAME enters the battlefield tapped unless you control a Swamp. A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B}. -A:AB$ Draw | Cost$ 1 B B T | NumCards$ 1 | SpellDescription$ Draw a card, then you lose life equal to the number of cards in your hand. | SubAbility$ DBLoseLife -SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ X +A:AB$ Draw | Cost$ 1 B B T | NumCards$ 1 | SpellDescription$ Draw a card, then you lose life equal to the number of cards in your hand. | SubAbility$ DBLoseLife | StackDescription$ SpellDescription +SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ X | StackDescription$ None SVar:X:Count$InYourHand Oracle:Castle Locthwain enters the battlefield tapped unless you control a Swamp.\n{T}: Add {B}.\n{1}{B}{B}, {T}: Draw a card, then you lose life equal to the number of cards in your hand. diff --git a/forge-gui/res/cardsfolder/c/cemetery_desecrator.txt b/forge-gui/res/cardsfolder/c/cemetery_desecrator.txt index 33e9ffaa5a9..d7af628e4b4 100644 --- a/forge-gui/res/cardsfolder/c/cemetery_desecrator.txt +++ b/forge-gui/res/cardsfolder/c/cemetery_desecrator.txt @@ -5,11 +5,11 @@ PT:4/4 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield or dies, exile another card from a graveyard. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | Secondary$ True | TriggerDescription$ When CARDNAME enters the battlefield or dies, exile another card from a graveyard. SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | Hidden$ True | RememberChanged$ True | ChangeType$ Card.Other | ChangeNum$ 1 | Mandatory$ True | AILogic$ ExilePreference:HighestCMC | SubAbility$ DBImmediateTrigger -SVar:DBImmediateTrigger:DB$ ImmediateTrigger | ConditionDefined$ Remembered | ConditionPresent$ Card | Execute$ TrigCharm | TriggerDescription$ When you do, ABILITY +SVar:DBImmediateTrigger:DB$ ImmediateTrigger | ConditionDefined$ Remembered | ConditionPresent$ Card | RememberObjects$ Remembered | SubAbility$ DBCleanup | Execute$ TrigCharm | TriggerDescription$ When you do, ABILITY SVar:TrigCharm:DB$ Charm | Choices$ DBRemoveCounter,DBPump -SVar:DBRemoveCounter:DB$ RemoveCounter | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | CounterType$ Any | CounterNum$ X | SubAbility$ DBCleanup | SpellDescription$ Remove X counters from target permanent, where X is the mana value of the exiled card. -SVar:DBPump:DB$ Pump | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls | IsCurse$ True | NumAtt$ -X | NumDef$ -X | SubAbility$ DBCleanup | SpellDescription$ Target creature an opponent controls gets -X/-X until end of turn, where X is the mana value of the exiled card. +SVar:DBRemoveCounter:DB$ RemoveCounter | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | CounterType$ Any | CounterNum$ X | SpellDescription$ Remove X counters from target permanent, where X is the mana value of the exiled card. +SVar:DBPump:DB$ Pump | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls | IsCurse$ True | NumAtt$ -X | NumDef$ -X | SpellDescription$ Target creature an opponent controls gets -X/-X until end of turn, where X is the mana value of the exiled card. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:X:Remembered$CardManaCost +SVar:X:TriggerRemembered$CardManaCost DeckHas:Ability$Graveyard Oracle:Menace\nWhen Cemetery Desecrator enters the battlefield or dies, exile another card from a graveyard. When you do, choose one —\n• Remove X counters from target permanent, where X is the mana value of the exiled card.\n• Target creature an opponent controls gets -X/-X until end of turn, where X is the mana value of the exiled card. diff --git a/forge-gui/res/cardsfolder/c/consulate_turret.txt b/forge-gui/res/cardsfolder/c/consulate_turret.txt index 5ee544139e4..68ddf2adc96 100644 --- a/forge-gui/res/cardsfolder/c/consulate_turret.txt +++ b/forge-gui/res/cardsfolder/c/consulate_turret.txt @@ -1,7 +1,7 @@ Name:Consulate Turret ManaCost:3 Types:Artifact -A:AB$ PutCounter | Cost$ T | Defined$ You | CounterType$ ENERGY | CounterNum$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ You get {E} (an energy counter). +A:AB$ PutCounter | Cost$ T | Defined$ You | CounterType$ ENERGY | CounterNum$ 1 | AILogic$ AtOppEOT | SpellDescription$ You get {E} (an energy counter). A:AB$ DealDamage | Cost$ T PayEnergy<3> | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select target player or planeswalker | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to target player or planeswalker. SVar:Picture:http://www.wizards.com/global/images/magic/general/consulate_turret.jpg Oracle:{T}: You get {E} (an energy counter).\n{T}, Pay {E}{E}{E}: Consulate Turret deals 2 damage to target player or planeswalker. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/c/curse_of_opulence.txt b/forge-gui/res/cardsfolder/c/curse_of_opulence.txt index 6bdcca572a5..615942a8c45 100644 --- a/forge-gui/res/cardsfolder/c/curse_of_opulence.txt +++ b/forge-gui/res/cardsfolder/c/curse_of_opulence.txt @@ -5,5 +5,5 @@ K:Enchant player A:SP$ Attach | Cost$ R | ValidTgts$ Player | AILogic$ Curse T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigRepeat | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, create a Gold token. Each opponent attacking that player does the same. (A Gold token is an artifact with "Sacrifice this artifact: Add one mana of any color.") SVar:TrigRepeat:DB$ RepeatEach | RepeatPlayers$ TriggeredAttackingPlayerAndYou | RepeatSubAbility$ TrigToken | ChangeZoneTable$ True -SVar:TrigToken:DB$ Token | TokenScript$ gold | TokenOwner$ Player.IsRemembered | TokenAmount$ 1 | LegacyImage$ gold c17 +SVar:TrigToken:DB$ Token | TokenScript$ c_a_gold_draw | TokenOwner$ Player.IsRemembered | TokenAmount$ 1 Oracle:Enchant player\nWhenever enchanted player is attacked, create a Gold token. Each opponent attacking that player does the same. (A Gold token is an artifact with "Sacrifice this artifact: Add one mana of any color.") diff --git a/forge-gui/res/cardsfolder/d/damping_matrix.txt b/forge-gui/res/cardsfolder/d/damping_matrix.txt index fa63c25b8e4..08dbd353f09 100644 --- a/forge-gui/res/cardsfolder/d/damping_matrix.txt +++ b/forge-gui/res/cardsfolder/d/damping_matrix.txt @@ -1,7 +1,7 @@ Name:Damping Matrix ManaCost:3 Types:Artifact -S:Mode$ CantBeActivated | ValidCard$ Artifact,Creature | AffectedZone$ Battlefield | NonMana$ True | Description$ Activated abilities of artifacts and creatures can't be activated unless they're mana abilities. +S:Mode$ CantBeActivated | ValidCard$ Artifact,Creature | ValidSA$ Activated.nonManaAbility | AffectedZone$ Battlefield | Description$ Activated abilities of artifacts and creatures can't be activated unless they're mana abilities. SVar:NonStackingEffect:True AI:RemoveDeck:Random SVar:Picture:http://www.wizards.com/global/images/magic/general/damping_matrix.jpg diff --git a/forge-gui/res/cardsfolder/d/dancing_sword.txt b/forge-gui/res/cardsfolder/d/dancing_sword.txt index 3ed2a648f89..aff64b1025f 100644 --- a/forge-gui/res/cardsfolder/d/dancing_sword.txt +++ b/forge-gui/res/cardsfolder/d/dancing_sword.txt @@ -3,6 +3,6 @@ ManaCost:1 W Types:Artifact Equipment S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 2 | AddToughness$ 1 | Description$ Equipped creature gets +2/+1. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.AttachedBy | Execute$ TrigAnimate | OptionalDecider$ You | TriggerDescription$ When equipped creature dies, you may have CARDNAME become a 2/1 Construct artifact creature with flying and ward {1}. If you do, it isn't an Equipment. -SVar:TrigAnimate:DB$ Animate | Defined$ Self | Types$ Artifact,Creature,Construct | Power$ 2 | Toughness$ 1 | Keywords$ Flying & Ward:1 | RemoveCardTypes$ True | RemoveSubTypes$ True | Duration$ Permanent +SVar:TrigAnimate:DB$ Animate | Defined$ Self | Types$ Artifact,Creature,Construct | Power$ 2 | Toughness$ 1 | Keywords$ Flying & Ward:1 | RemoveCardTypes$ True | RemoveCreatureTypes$ True | RemoveTypes$ Equipment | Duration$ Permanent K:Equip:1 Oracle:Equipped creature gets +2/+1.\nWhen equipped creature dies, you may have Dancing Sword become a 2/1 Construct artifact creature with flying and ward {1}. If you do, it isn't an Equipment.\nEquip {1} diff --git a/forge-gui/res/cardsfolder/d/divergent_transformations.txt b/forge-gui/res/cardsfolder/d/divergent_transformations.txt index b49867d198d..6ff7d58f348 100644 --- a/forge-gui/res/cardsfolder/d/divergent_transformations.txt +++ b/forge-gui/res/cardsfolder/d/divergent_transformations.txt @@ -2,10 +2,9 @@ Name:Divergent Transformations ManaCost:6 R Types:Instant K:Undaunted -A:SP$ ChangeZone | Cost$ 6 R | ValidTgts$ Creature | TargetMin$ 2 | TargetMax$ 2 | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBTransform | SpellDescription$ Exile two target creatures. For each of those creatures, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then shuffles the rest into their library. +A:SP$ ChangeZone | Cost$ 6 R | ValidTgts$ Creature | TargetMin$ 2 | TargetMax$ 2 | Origin$ Battlefield | Destination$ Exile | RememberLKI$ True | SubAbility$ DBTransform | SpellDescription$ Exile two target creatures. For each of those creatures, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then shuffles the rest into their library. SVar:DBTransform:DB$ RepeatEach | UseImprinted$ True | DefinedCards$ DirectRemembered | ChooseOrder$ True | Zone$ Exile | RepeatSubAbility$ DBReveal | SubAbility$ DBCleanRemembered -SVar:DBReveal:DB$ DigUntil | Defined$ ImprintedController | Amount$ 1 | Valid$ Creature | ValidDescription$ creature | RevealedDestination$ Library | RevealedLibraryPosition$ 0 | FoundDestination$ Battlefield | SubAbility$ DBCleanup | Shuffle$ True -SVar:DBCleanup:DB$ Cleanup | ClearImprinted$ True +SVar:DBReveal:DB$ DigUntil | Defined$ ImprintedController | Amount$ 1 | Valid$ Creature | ValidDescription$ creature | RevealedDestination$ Library | RevealedLibraryPosition$ 0 | FoundDestination$ Battlefield | Shuffle$ True SVar:DBCleanRemembered:DB$ Cleanup | ClearRemembered$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/divergent_transformations.jpg Oracle:Undaunted (This spell costs {1} less to cast for each opponent.)\nExile two target creatures. For each of those creatures, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then shuffles the rest into their library. diff --git a/forge-gui/res/cardsfolder/d/dreamshackle_geist.txt b/forge-gui/res/cardsfolder/d/dreamshackle_geist.txt index 29644fa782b..67e3fb23277 100644 --- a/forge-gui/res/cardsfolder/d/dreamshackle_geist.txt +++ b/forge-gui/res/cardsfolder/d/dreamshackle_geist.txt @@ -4,7 +4,7 @@ Types:Creature Spirit PT:3/1 K:Flying T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | Execute$ TrigCharm | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of combat on your turn, ABILITY -SVar:TrigCharm:DB$ Charm | Choices$ Tap,Freeze | CharmNum$ 1 +SVar:TrigCharm:DB$ Charm | Choices$ Tap,Freeze | CharmNum$ 1 | MinCharmNum$ 0 SVar:Tap:DB$ Tap | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Tap target creature. SVar:Freeze:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN This card doesn't untap during your next untap step. | Duration$ Permanent | IsCurse$ True | SpellDescription$ Target creature doesn't untap during its controller's next untap step. Oracle:Flying\nAt the beginning of combat on your turn, choose up to one —\n• Tap target creature.\n• Target creature doesn't untap during its controller's next untap step. diff --git a/forge-gui/res/cardsfolder/d/dwarven_sea_clan.txt b/forge-gui/res/cardsfolder/d/dwarven_sea_clan.txt index 7018400b297..2de9c45e0db 100644 --- a/forge-gui/res/cardsfolder/d/dwarven_sea_clan.txt +++ b/forge-gui/res/cardsfolder/d/dwarven_sea_clan.txt @@ -2,7 +2,7 @@ Name:Dwarven Sea Clan ManaCost:2 R Types:Creature Dwarf PT:1/1 -A:AB$ Pump | Cost$ T | IsCurse$ True | ValidTgts$ Creature.ControllerControlsIsland+attacking,Creature.ControllerControlsIsland+blocking | TgtPrompt$ Select target attacking or blocking creature whose controller controls an Island | ActivationPhases$ BeginCombat->Combat Damage | ConditionDefined$ Targeted | ConditionPresent$ Creature.ControllerControlsIsland | ConditionCompare$ GE1 | SubAbility$ DBDelayTrig | StackDescription$ SpellDescription | SpellDescription$ Choose target attacking or blocking creature whose controller controls an Island. CARDNAME deals 2 damage to that creature at end of combat. Activate only before the end of combat step. +A:AB$ Pump | Cost$ T | IsCurse$ True | ValidTgts$ Creature.ControllerControlsIsland+attacking,Creature.ControllerControlsIsland+blocking | TgtPrompt$ Select target attacking or blocking creature whose controller controls an Island | ActivationPhases$ BeginCombat->Combat Damage | ActivationFirstCombat$ True | ConditionDefined$ Targeted | ConditionPresent$ Creature.ControllerControlsIsland | ConditionCompare$ GE1 | SubAbility$ DBDelayTrig | StackDescription$ SpellDescription | SpellDescription$ Choose target attacking or blocking creature whose controller controls an Island. CARDNAME deals 2 damage to that creature at end of combat. Activate only before the end of combat step. SVar:DBDelayTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | Execute$ TrigDmg | SpellDescription$ CARDNAME deals 2 damage to that creature at end of combat. | RememberObjects$ ParentTarget | SubAbility$ DBCleanup SVar:TrigDmg:DB$ DealDamage | NumDmg$ 2 | Defined$ DelayTriggerRemembered SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/e/erebos_god_of_the_dead.txt b/forge-gui/res/cardsfolder/e/erebos_god_of_the_dead.txt index 4e99c401ca2..747afe6a85f 100644 --- a/forge-gui/res/cardsfolder/e/erebos_god_of_the_dead.txt +++ b/forge-gui/res/cardsfolder/e/erebos_god_of_the_dead.txt @@ -5,9 +5,8 @@ PT:5/7 K:Indestructible S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT5 | Description$ As long as your devotion to black is less than 5, CARDNAME isn't a creature. (Each {B} in the mana costs of permanents you control counts towards your devotion to black.) SVar:X:Count$Devotion.Black -S:Mode$ Continuous | Affected$ Player.Opponent | AddKeyword$ You can't gain life. | Description$ Your opponents can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Player.Opponent | Description$ Your opponents can't gain life. A:AB$ Draw | Cost$ 1 B PayLife<2> | NumCards$ 1 | SpellDescription$ Draw a card. SVar:PlayMain1:TRUE SVar:BuffedBy:Permanent.Black -SVar:Picture:http://www.wizards.com/global/images/magic/general/erebos_god_of_the_dead.jpg Oracle:Indestructible\nAs long as your devotion to black is less than five, Erebos isn't a creature. (Each {B} in the mana costs of permanents you control counts toward your devotion to black.)\nYour opponents can't gain life.\n{1}{B}, Pay 2 life: Draw a card. diff --git a/forge-gui/res/cardsfolder/e/everlasting_torment.txt b/forge-gui/res/cardsfolder/e/everlasting_torment.txt index c54cb3fc17d..9bebb75958e 100644 --- a/forge-gui/res/cardsfolder/e/everlasting_torment.txt +++ b/forge-gui/res/cardsfolder/e/everlasting_torment.txt @@ -1,7 +1,7 @@ Name:Everlasting Torment ManaCost:2 BR Types:Enchantment -S:Mode$ Continuous | Affected$ Player | AddKeyword$ You can't gain life. | Description$ Players can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Player | Description$ Players can't gain life. S:Mode$ CantPreventDamage | Description$ Damage can't be prevented. S:Mode$ Continuous | GlobalRule$ All damage is dealt as though its source had wither. | Description$ All damage is dealt as though its source had wither. (A source with wither deals damage to creatures in the form of -1/-1 counters.) SVar:NonStackingEffect:True diff --git a/forge-gui/res/cardsfolder/f/fabrication_module.txt b/forge-gui/res/cardsfolder/f/fabrication_module.txt index 1555f0e9c08..3e703549e91 100644 --- a/forge-gui/res/cardsfolder/f/fabrication_module.txt +++ b/forge-gui/res/cardsfolder/f/fabrication_module.txt @@ -3,7 +3,7 @@ ManaCost:3 Types:Artifact T:Mode$ CounterAddedOnce | ValidPlayer$ You | TriggerZones$ Battlefield | CounterType$ ENERGY | Execute$ TrigPutCounter | TriggerDescription$ Whenever you get one or more {E} (energy counters), put a +1/+1 counter on target creature you control. SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | CounterType$ P1P1 | CounterNum$ 1 -A:AB$ PutCounter | Cost$ 4 T | Defined$ You | CounterType$ ENERGY | CounterNum$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ You get {E}. +A:AB$ PutCounter | Cost$ 4 T | Defined$ You | CounterType$ ENERGY | CounterNum$ 1 | AILogic$ AtOppEOT | SpellDescription$ You get {E}. DeckHas:Ability$Counters SVar:Picture:http://www.wizards.com/global/images/magic/general/fabrication_module.jpg Oracle:Whenever you get one or more {E} (energy counters), put a +1/+1 counter on target creature you control.\n{4}, {T}: You get {E}. diff --git a/forge-gui/res/cardsfolder/f/faceless_haven.txt b/forge-gui/res/cardsfolder/f/faceless_haven.txt index 84bf650db55..b964a78814c 100644 --- a/forge-gui/res/cardsfolder/f/faceless_haven.txt +++ b/forge-gui/res/cardsfolder/f/faceless_haven.txt @@ -2,6 +2,6 @@ Name:Faceless Haven ManaCost:no cost Types:Snow Land A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. -A:AB$ Animate | Cost$ S S S | Defined$ Self | Power$ 4 | Toughness$ 3 | Types$ Creature,AllCreatureTypes | Keywords$ Vigilance | StackDescription$ CARDNAME becomes a 4/3 creature with vigilance and all creature types until end of turn. It's still a land. | SpellDescription$ CARDNAME becomes a 4/3 creature with vigilance and all creature types until end of turn. It's still a land. ({S} can be paid with one mana from a snow source.) +A:AB$ Animate | Cost$ S S S | Defined$ Self | Power$ 4 | Toughness$ 3 | Types$ Creature | AddAllCreatureTypes$ True | Keywords$ Vigilance | StackDescription$ CARDNAME becomes a 4/3 creature with vigilance and all creature types until end of turn. It's still a land. | SpellDescription$ CARDNAME becomes a 4/3 creature with vigilance and all creature types until end of turn. It's still a land. ({S} can be paid with one mana from a snow source.) DeckNeeds:Type$Snow Oracle:{T}: Add {C}.\n{S}{S}{S}: Faceless Haven becomes a 4/3 creature with vigilance and all creature types until end of turn. It's still a land. ({S} can be paid with one mana from a snow source.) diff --git a/forge-gui/res/cardsfolder/f/faiths_fetters.txt b/forge-gui/res/cardsfolder/f/faiths_fetters.txt index c129eb5e70b..35465b2d05d 100644 --- a/forge-gui/res/cardsfolder/f/faiths_fetters.txt +++ b/forge-gui/res/cardsfolder/f/faiths_fetters.txt @@ -5,7 +5,7 @@ K:Enchant permanent A:SP$ Attach | Cost$ 3 W | ValidTgts$ Permanent | AITgts$ Creature | AILogic$ Curse T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME enters the battlefield, you gain 4 life. SVar:TrigGainLife:DB$ GainLife | LifeAmount$ 4 -S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | NonMana$ True | Description$ Enchanted permanent can't attack or block, and its activated abilities can't be activated unless they're mana abilities. +S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | ValidSA$ Activated.nonManaAbility | Description$ Enchanted permanent can't attack or block, and its activated abilities can't be activated unless they're mana abilities. S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block. DeckHas:Ability$LifeGain SVar:Picture:http://www.wizards.com/global/images/magic/general/faiths_fetters.jpg diff --git a/forge-gui/res/cardsfolder/f/flamescroll_celebrant_revel_in_silence.txt b/forge-gui/res/cardsfolder/f/flamescroll_celebrant_revel_in_silence.txt index 163d80c8176..5b76c47bc79 100644 --- a/forge-gui/res/cardsfolder/f/flamescroll_celebrant_revel_in_silence.txt +++ b/forge-gui/res/cardsfolder/f/flamescroll_celebrant_revel_in_silence.txt @@ -16,5 +16,5 @@ Types:Instant A:SP$ Effect | Cost$ W | Name$ Silence Effect | StaticAbilities$ STCantBeCast,STCantBeActivated | AILogic$ BeginningOfOppTurn | SubAbility$ DBChange | StackDescription$ SpellDescription | SpellDescription$ Your opponents can't cast spells or activate planeswalkers' loyalty abilities this turn. Exile CARDNAME. SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | StackDescription$ None SVar:STCantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ Opponent | Description$ Your opponents can't cast spells. -SVar:STCantBeActivated:Mode$ CantBeActivated | Activator$ Opponent | EffectZone$ Command | ValidCard$ Planeswalker | Loyalty$ True | Description$ Your opponents can't activate planeswalkers' loyalty abilities. +SVar:STCantBeActivated:Mode$ CantBeActivated | Activator$ Opponent | EffectZone$ Command | ValidCard$ Planeswalker | ValidSA$ Activated.Loyalty | Description$ Your opponents can't activate planeswalkers' loyalty abilities. Oracle:Your opponents can't cast spells or activate planeswalkers' loyalty abilities this turn.\nExile Revel in Silence. diff --git a/forge-gui/res/cardsfolder/f/forsaken_wastes.txt b/forge-gui/res/cardsfolder/f/forsaken_wastes.txt index d05ca44ec40..7aa5e5dcbc7 100644 --- a/forge-gui/res/cardsfolder/f/forsaken_wastes.txt +++ b/forge-gui/res/cardsfolder/f/forsaken_wastes.txt @@ -1,11 +1,10 @@ Name:Forsaken Wastes ManaCost:2 B Types:World Enchantment -S:Mode$ Continuous | Affected$ Player | AddKeyword$ You can't gain life. | Description$ Players can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Player | Description$ Players can't gain life. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | Execute$ TrigLoseLife | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each player's upkeep, that player loses 1 life. T:Mode$ BecomesTarget | ValidTarget$ Card.Self | SourceType$ Spell | Execute$ TrigLoseLife5 | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME becomes the target of a spell, that spell's controller loses 5 life. SVar:TrigLoseLife:DB$ LoseLife | Defined$ TriggeredPlayer | LifeAmount$ 1 SVar:TrigLoseLife5:DB$ LoseLife | Defined$ TriggeredSourceController | LifeAmount$ 5 AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/forsaken_wastes.jpg Oracle:Players can't gain life.\nAt the beginning of each player's upkeep, that player loses 1 life.\nWhenever Forsaken Wastes becomes the target of a spell, that spell's controller loses 5 life. diff --git a/forge-gui/res/cardsfolder/g/gallia_of_the_endless_dance.txt b/forge-gui/res/cardsfolder/g/gallia_of_the_endless_dance.txt index 2ac298f5888..a20bd43f2cb 100644 --- a/forge-gui/res/cardsfolder/g/gallia_of_the_endless_dance.txt +++ b/forge-gui/res/cardsfolder/g/gallia_of_the_endless_dance.txt @@ -6,6 +6,6 @@ K:Haste S:Mode$ Continuous | Affected$ Card.Satyr+Other+YouCtrl | AddPower$ 1 | AddToughness$ 1 | AddKeyword$ Haste | Description$ Other Satyrs you control get +1/+1 and have haste. T:Mode$ AttackersDeclared | Execute$ TrigDiscard | CheckSVar$ AttackerCount | SVarCompare$ GE3 | NoResolvingCheck$ True | TriggerZones$ Battlefield | AttackingPlayer$ You | TriggerDescription$ Whenever you attack with three or more creatures, you may discard a card at random. If you do, draw two cards. SVar:AttackerCount:Count$Valid Creature.attacking -SVar:TrigDiscard:AB$ Draw | Defined$ You | NumCards$ 2 | Cost$ Discard<1/Random> +SVar:TrigDiscard:DB$ Draw | Defined$ You | NumCards$ 2 | UnlessCost$ Discard<1/Random> | UnlessPayer$ You | UnlessSwitched$ True DeckHints:Type$Satyr -Oracle:Haste\nOther Satyrs you control get +1/+1 and have haste.\nWhenever you attack with three or more creatures, you may discard a card at random. If you do, draw two cards. \ No newline at end of file +Oracle:Haste\nOther Satyrs you control get +1/+1 and have haste.\nWhenever you attack with three or more creatures, you may discard a card at random. If you do, draw two cards. diff --git a/forge-gui/res/cardsfolder/g/gild.txt b/forge-gui/res/cardsfolder/g/gild.txt index 36b0e11dcbc..8856163616b 100644 --- a/forge-gui/res/cardsfolder/g/gild.txt +++ b/forge-gui/res/cardsfolder/g/gild.txt @@ -2,5 +2,5 @@ Name:Gild ManaCost:3 B Types:Sorcery A:SP$ ChangeZone | Cost$ 3 B | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBToken | SpellDescription$ Exile target creature. Create a Gold token. (It's an artifact with "Sacrifice this artifact: Add one mana of any color.") -SVar:DBToken:DB$ Token | TokenScript$ gold | TokenOwner$ You | LegacyImage$ gold bng +SVar:DBToken:DB$ Token | TokenScript$ c_a_gold_draw | TokenOwner$ You Oracle:Exile target creature. Create a Gold token. (It's an artifact with "Sacrifice this artifact: Add one mana of any color.") diff --git a/forge-gui/res/cardsfolder/g/goblin_welder.txt b/forge-gui/res/cardsfolder/g/goblin_welder.txt index 70e30b2c1de..6ccf8bd2f07 100644 --- a/forge-gui/res/cardsfolder/g/goblin_welder.txt +++ b/forge-gui/res/cardsfolder/g/goblin_welder.txt @@ -2,11 +2,14 @@ Name:Goblin Welder ManaCost:R Types:Creature Goblin Artificer PT:1/1 -A:AB$ Pump | Cost$ T | ValidTgts$ Artifact | TgtPrompt$ Select target artifact a player controls | RememberObjects$ ThisTargetedCard | Condition$ AllTargetsLegal | SubAbility$ DBTargetYard | SpellDescription$ Choose target artifact a player controls and target artifact card in that player's graveyard. If both targets are still legal as this ability resolves, that player simultaneously sacrifices the artifact and returns the artifact card to the battlefield. | StackDescription$ None -SVar:DBTargetYard:DB$ Pump | ValidTgts$ Artifact | TgtPrompt$ Select target artifact card in that player's graveyard | TgtZone$ Graveyard | PumpZone$ Graveyard | TargetsWithSameController$ True | ImprintCards$ ThisTargetedCard | Condition$ AllTargetsLegal | StackDescription$ If both targets are still legal as this ability resolves, {p:TargetedController} simultaneously sacrifices {c:ParentTarget} and returns {c:Targeted} to the battlefield. | SubAbility$ DBSacrifice -SVar:DBSacrifice:DB$ SacrificeAll | ValidCards$ Card.IsRemembered | ConditionDefined$ Remembered | ConditionPresent$ Artifact | ConditionCompare$ GE1 | ConditionCheckSVar$ CheckImprint | ConditionSVarCompare$ GE1 | SubAbility$ DBReturn | StackDescription$ None -SVar:DBReturn:DB$ ChangeZone | Defined$ Imprinted | Origin$ Graveyard | Destination$ Battlefield | SubAbility$ DBCleanup | ConditionDefined$ Remembered | ConditionPresent$ Artifact | ConditionCompare$ GE1 | ConditionCheckSVar$ CheckImprint | ConditionSVarCompare$ GE1 | StackDescription$ None +A:AB$ Pump | Cost$ T | ValidTgts$ Artifact | TgtPrompt$ Select target artifact a player controls | RememberObjects$ ThisTargetedCard | Condition$ AllTargetsLegal | SubAbility$ DBTargetYard | StackDescription$ If both targets are still legal as this ability resolves, {p:TargetedController} simultaneously sacrifices {c:ThisTargetedCard} | SpellDescription$ Choose target artifact a player controls and target artifact card in that player's graveyard. If both targets are still legal as this ability resolves, that player simultaneously sacrifices the artifact and returns the artifact card to the battlefield. +SVar:DBTargetYard:DB$ Pump | ValidTgts$ Artifact | TargetsWithDefinedController$ ParentTargetedController | TgtPrompt$ Select target artifact card in that player's graveyard | TgtZone$ Graveyard | PumpZone$ Graveyard | ImprintCards$ ThisTargetedCard | Condition$ AllTargetsLegal | StackDescription$ and returns {c:ThisTargetedCard} to the battlefield. | SubAbility$ DBBranch +SVar:DBBranch:DB$ Branch | BranchConditionSVar$ TargetCheck | BranchConditionSVarCompare$ GE2 | TrueSubAbility$ DBSacrifice | FalseSubAbility$ DBCleanup +SVar:DBSacrifice:DB$ SacrificeAll | ValidCards$ Card.IsRemembered | SubAbility$ DBReturn +SVar:DBReturn:DB$ ChangeZone | Defined$ Imprinted | Origin$ Graveyard | Destination$ Battlefield | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True +SVar:TargetCheck:SVar$CheckRemem/Plus.CheckImprint +SVar:CheckRemem:Remembered$Valid Artifact.sharesControllerWith Imprinted SVar:CheckImprint:Imprinted$Valid Artifact.sharesControllerWith Remembered AI:RemoveDeck:All AI:RemoveDeck:Random diff --git a/forge-gui/res/cardsfolder/h/halana_and_alena_partners.txt b/forge-gui/res/cardsfolder/h/halana_and_alena_partners.txt index 3c3a8b17a54..18f835b60eb 100644 --- a/forge-gui/res/cardsfolder/h/halana_and_alena_partners.txt +++ b/forge-gui/res/cardsfolder/h/halana_and_alena_partners.txt @@ -2,10 +2,11 @@ Name:Halana and Alena, Partners ManaCost:2 R G Types:Legendary Creature Human Ranger PT:2/3 +K:Reach +K:First Strike T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of combat on your turn, put X +1/+1 counters on another target creature you control, where X is NICKNAME's power. That creature gains haste until end of turn. SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature.Other+YouCtrl | TgtPrompt$ Select another target creature you control | CounterType$ P1P1 | CounterNum$ X | SubAbility$ DBPump SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ Haste SVar:X:Count$CardPower DeckHas:Ability$Counters -Oracle:First strike, reach -Oracle:At the beginning of combat on your turn, put X +1/+1 counters on another target creature you control, where X is Halana and Alena's power. That creature gains haste until end of turn. +Oracle:First strike, reach\nAt the beginning of combat on your turn, put X +1/+1 counters on another target creature you control, where X is Halana and Alena's power. That creature gains haste until end of turn. diff --git a/forge-gui/res/cardsfolder/h/hand_to_hand.txt b/forge-gui/res/cardsfolder/h/hand_to_hand.txt index dcd5bca5a1f..00b95a87e5b 100644 --- a/forge-gui/res/cardsfolder/h/hand_to_hand.txt +++ b/forge-gui/res/cardsfolder/h/hand_to_hand.txt @@ -2,7 +2,7 @@ Name:Hand to Hand ManaCost:2 R Types:Enchantment S:Mode$ CantBeCast | ValidCard$ Instant | Phases$ BeginCombat->EndCombat | Description$ During combat, players can't cast instant spells or activate abilities that aren't mana abilities. -S:Mode$ CantBeActivated | ValidCard$ Card | Phases$ BeginCombat->EndCombat | NonMana$ True +S:Mode$ CantBeActivated | ValidCard$ Card | Phases$ BeginCombat->EndCombat | ValidSA$ Activated.nonManaAbility SVar:NonStackingEffect:True AI:RemoveDeck:Random SVar:Picture:http://www.wizards.com/global/images/magic/general/hand_to_hand.jpg diff --git a/forge-gui/res/cardsfolder/h/hatchery_spider.txt b/forge-gui/res/cardsfolder/h/hatchery_spider.txt index aa6137ccdad..8e99ff39b82 100644 --- a/forge-gui/res/cardsfolder/h/hatchery_spider.txt +++ b/forge-gui/res/cardsfolder/h/hatchery_spider.txt @@ -4,6 +4,6 @@ Types:Creature Spider PT:5/7 K:Reach T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ Undergrowth - When you cast this spell, reveal the top X cards of your library, where X is the number of creature cards in your graveyard. You may put a green permanent card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. -SVar:TrigDig:DB$ Dig | DigNum$ X | Reveal$ True | ChangeNum$ 1 | ChangeValid$ Permanent.Green+cmcLEX | DestinationZone$ Battlefield | AILogic$ AtOppEndOfTurn | Optional$ True | RestRandomOrder$ True +SVar:TrigDig:DB$ Dig | DigNum$ X | Reveal$ True | ChangeNum$ 1 | ChangeValid$ Permanent.Green+cmcLEX | DestinationZone$ Battlefield | AILogic$ AtOppEOT | Optional$ True | RestRandomOrder$ True SVar:X:Count$TypeInYourYard.Creature Oracle:Reach\nUndergrowth — When you cast this spell, reveal the top X cards of your library, where X is the number of creature cards in your graveyard. You may put a green permanent card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/h/havoc_festival.txt b/forge-gui/res/cardsfolder/h/havoc_festival.txt index e0eb3cc357a..382465d7dcd 100644 --- a/forge-gui/res/cardsfolder/h/havoc_festival.txt +++ b/forge-gui/res/cardsfolder/h/havoc_festival.txt @@ -1,10 +1,9 @@ Name:Havoc Festival ManaCost:4 B R Types:Enchantment -S:Mode$ Continuous | Affected$ Player | AddKeyword$ You can't gain life. | Description$ Players can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Player | Description$ Players can't gain life. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | TriggerZones$ Battlefield | Execute$ TrigLoseLife | TriggerDescription$ At the beginning of each player's upkeep, that player loses half their life, rounded up. SVar:TrigLoseLife:DB$ LoseLife | Defined$ TriggeredPlayer | LifeAmount$ HavocX SVar:HavocX:TriggeredPlayer$LifeTotal/HalfUp AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/havoc_festival.jpg Oracle:Players can't gain life.\nAt the beginning of each player's upkeep, that player loses half their life, rounded up. diff --git a/forge-gui/res/cardsfolder/h/horizon_stone.txt b/forge-gui/res/cardsfolder/h/horizon_stone.txt index 8c29ce57165..1c32f21e733 100644 --- a/forge-gui/res/cardsfolder/h/horizon_stone.txt +++ b/forge-gui/res/cardsfolder/h/horizon_stone.txt @@ -1,5 +1,5 @@ Name:Horizon Stone ManaCost:5 Types:Artifact -S:Mode$ Continuous | Affected$ You | AddKeyword$ Convert unused mana to Colorless | Description$ If you would lose unspent mana, that mana becomes colorless instead. +R:Event$ LoseMana | ValidPlayer$ You | ReplacementResult$ Replaced | ActiveZones$ Battlefield | Description$ If you would lose unspent mana, that mana becomes colorless instead. Oracle:If you would lose unspent mana, that mana becomes colorless instead. diff --git a/forge-gui/res/cardsfolder/k/katabatic_winds.txt b/forge-gui/res/cardsfolder/k/katabatic_winds.txt index 28f56769d5d..0d5fe2d7459 100644 --- a/forge-gui/res/cardsfolder/k/katabatic_winds.txt +++ b/forge-gui/res/cardsfolder/k/katabatic_winds.txt @@ -3,7 +3,7 @@ ManaCost:2 G Types:Enchantment K:Phasing S:Mode$ Continuous | Affected$ Creature.withFlying | AddHiddenKeyword$ CARDNAME can't attack or block. | Description$ Creatures with flying can't attack or block, and their activated abilities with {T} in their costs can't be activated. -S:Mode$ CantBeActivated | ValidCard$ Creature.withFlying | AffectedZone$ Battlefield | TapAbility$ True +S:Mode$ CantBeActivated | ValidCard$ Creature.withFlying | ValidSA$ Activated.hasTapCost | AffectedZone$ Battlefield AI:RemoveDeck:Random SVar:Picture:http://www.wizards.com/global/images/magic/general/katabatic_winds.jpg Oracle:Phasing (This phases in or out before you untap during each of your untap steps. While it's phased out, it's treated as though it doesn't exist.)\nCreatures with flying can't attack or block, and their activated abilities with {T} in their costs can't be activated. diff --git a/forge-gui/res/cardsfolder/k/key_to_the_city.txt b/forge-gui/res/cardsfolder/k/key_to_the_city.txt index e9d7986bf0e..2172a807570 100644 --- a/forge-gui/res/cardsfolder/k/key_to_the_city.txt +++ b/forge-gui/res/cardsfolder/k/key_to_the_city.txt @@ -3,6 +3,6 @@ ManaCost:2 Types:Artifact A:AB$ Pump | Cost$ T Discard<1/Card> | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ HIDDEN Unblockable | SpellDescription$ Up to one target creature can't be blocked this turn. T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever CARDNAME becomes untapped, you may pay {2}. If you do, draw a card. -SVar:TrigDraw:AB$Draw | Cost$ 2 | Defined$ You | NumCards$ 1 +SVar:TrigDraw:AB$ Draw | Cost$ 2 | Defined$ You | NumCards$ 1 SVar:Picture:http://www.wizards.com/global/images/magic/general/key_to_the_city.jpg Oracle:{T}, Discard a card: Up to one target creature can't be blocked this turn.\nWhenever Key to the City becomes untapped, you may pay {2}. If you do, draw a card. diff --git a/forge-gui/res/cardsfolder/k/king_macar_the_gold_cursed.txt b/forge-gui/res/cardsfolder/k/king_macar_the_gold_cursed.txt index 6fec53c4630..a8a1e49fd0e 100644 --- a/forge-gui/res/cardsfolder/k/king_macar_the_gold_cursed.txt +++ b/forge-gui/res/cardsfolder/k/king_macar_the_gold_cursed.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Human Noble PT:2/3 T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ Inspired — Whenever CARDNAME becomes untapped, you may exile target creature. If you do, create a Gold token. (It's an artifact with "Sacrifice this artifact: Add one mana of any color.") SVar:TrigExile:DB$ ChangeZone | ValidTgts$ Creature | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBToken -SVar:DBToken:DB$ Token | TokenScript$ gold | TokenOwner$ You | TokenAmount$ 1 | LegacyImage$ gold jou | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup +SVar:DBToken:DB$ Token | TokenScript$ c_a_gold_draw | TokenOwner$ You | TokenAmount$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Remembered$Amount Oracle:Inspired — Whenever King Macar, the Gold-Cursed becomes untapped, you may exile target creature. If you do, create a Gold token. (It's an artifact with "Sacrifice this artifact: Add one mana of any color.") diff --git a/forge-gui/res/cardsfolder/k/kruphix_god_of_horizons.txt b/forge-gui/res/cardsfolder/k/kruphix_god_of_horizons.txt index 00c42e9e931..d3098a79345 100644 --- a/forge-gui/res/cardsfolder/k/kruphix_god_of_horizons.txt +++ b/forge-gui/res/cardsfolder/k/kruphix_god_of_horizons.txt @@ -6,7 +6,7 @@ K:Indestructible S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | Description$ As long as your devotion to green and blue is less than seven, CARDNAME isn't a creature. SVar:X:Count$DevotionDual.Green.Blue S:Mode$ Continuous | Affected$ You | SetMaxHandSize$ Unlimited | Description$ You have no maximum hand size. -S:Mode$ Continuous | Affected$ You | AddKeyword$ Convert unused mana to Colorless | Description$ If you would lose unspent mana, that mana becomes colorless instead. +R:Event$ LoseMana | ValidPlayer$ You | ReplacementResult$ Replaced | ActiveZones$ Battlefield | Description$ If you would lose unspent mana, that mana becomes colorless instead. SVar:BuffedBy:Permanent.Green,Permanent.Blue SVar:Picture:http://www.wizards.com/global/images/magic/general/kruphix_god_of_horizons.jpg Oracle:Indestructible\nAs long as your devotion to green and blue is less than seven, Kruphix isn't a creature.\nYou have no maximum hand size.\nIf you would lose unspent mana, that mana becomes colorless instead. diff --git a/forge-gui/res/cardsfolder/k/kumena_tyrant_of_orazca.txt b/forge-gui/res/cardsfolder/k/kumena_tyrant_of_orazca.txt index f0629ec7537..3e88bb16cc2 100644 --- a/forge-gui/res/cardsfolder/k/kumena_tyrant_of_orazca.txt +++ b/forge-gui/res/cardsfolder/k/kumena_tyrant_of_orazca.txt @@ -3,7 +3,7 @@ ManaCost:1 G U Types:Legendary Creature Merfolk Shaman PT:2/4 A:AB$ Pump | Cost$ tapXType<1/Merfolk.Other> | CostDesc$ Tap another untapped Merfolk you control: | Defined$ Self | KW$ HIDDEN Unblockable | AILogic$ BeforeCombat | SpellDescription$ CARDNAME can't be blocked this turn. -A:AB$ Draw | Cost$ tapXType<3/Merfolk> | CostDesc$ Tap three untapped Merfolk you control: | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. +A:AB$ Draw | Cost$ tapXType<3/Merfolk> | CostDesc$ Tap three untapped Merfolk you control: | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card. A:AB$ PutCounterAll | Cost$ tapXType<5/Merfolk> | CostDesc$ Tap five untapped Merfolk you control: | ValidCards$ Merfolk.YouCtrl | CounterType$ P1P1 | CounterNum$ 1 | AILogic$ AtOppEOT | SpellDescription$ Put a +1/+1 counter on each Merfolk you control. DeckHints:Type$Merfolk SVar:BuffedBy:Merfolk diff --git a/forge-gui/res/cardsfolder/l/leyline_of_punishment.txt b/forge-gui/res/cardsfolder/l/leyline_of_punishment.txt index 586a0827abe..e210f0c6813 100644 --- a/forge-gui/res/cardsfolder/l/leyline_of_punishment.txt +++ b/forge-gui/res/cardsfolder/l/leyline_of_punishment.txt @@ -3,9 +3,8 @@ ManaCost:2 R R Types:Enchantment K:MayEffectFromOpeningHand:FromHand SVar:FromHand:DB$ ChangeZone | Defined$ Self | Origin$ Hand | Destination$ Battlefield | SpellDescription$ If CARDNAME is in your opening hand, you may begin the game with it on the battlefield. -S:Mode$ Continuous | Affected$ Player | AddKeyword$ You can't gain life. | Description$ Players can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Player | Description$ Players can't gain life. S:Mode$ CantPreventDamage | Description$ Damage can't be prevented. SVar:NonStackingEffect:True AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/leyline_of_punishment.jpg Oracle:If Leyline of Punishment is in your opening hand, you may begin the game with it on the battlefield.\nPlayers can't gain life.\nDamage can't be prevented. diff --git a/forge-gui/res/cardsfolder/l/leyline_tyrant.txt b/forge-gui/res/cardsfolder/l/leyline_tyrant.txt index b6ea1b08fce..f303211ffd3 100755 --- a/forge-gui/res/cardsfolder/l/leyline_tyrant.txt +++ b/forge-gui/res/cardsfolder/l/leyline_tyrant.txt @@ -3,7 +3,7 @@ ManaCost:2 R R Types:Creature Dragon PT:4/4 K:Flying -S:Mode$ Continuous | Affected$ You | AddKeyword$ Red mana doesn't empty from your mana pool as steps and phases end. | Description$ You don't lose unspent red mana as steps and phases end. +S:Mode$ UnspentMana | ValidPlayer$ You | ManaType$ Red | Description$ You don't lose unspent red mana as steps and phases end. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigChooseX | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you may pay any amount of {R}. When you do, it deals that much damage to any target. SVar:TrigChooseX:DB$ ChooseNumber | Defined$ You | ChooseAnyNumber$ True | ListTitle$ any amount of red mana | SubAbility$ DBDamage SVar:DBDamage:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target to damage with CARDNAME | NumDmg$ X | UnlessCost$ X | UnlessXColor$ R | UnlessSwitched$ True | UnlessPayer$ You diff --git a/forge-gui/res/cardsfolder/l/lord_of_tresserhorn.txt b/forge-gui/res/cardsfolder/l/lord_of_tresserhorn.txt index 22c4eadc2fa..9fd51085181 100644 --- a/forge-gui/res/cardsfolder/l/lord_of_tresserhorn.txt +++ b/forge-gui/res/cardsfolder/l/lord_of_tresserhorn.txt @@ -2,7 +2,7 @@ Name:Lord of Tresserhorn ManaCost:1 U B R Types:Legendary Creature Zombie PT:10/4 -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Self | Execute$ TrigLose | TriggerDescription$ When CARDNAME enters the battlefield, you lose 2 life, you sacrifice two creatures, and target opponent draws two cards. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Self | Execute$ TrigLose | AILogic$ BadETB | TriggerDescription$ When CARDNAME enters the battlefield, you lose 2 life, you sacrifice two creatures, and target opponent draws two cards. A:AB$ Regenerate | Cost$ B | SpellDescription$ Regenerate CARDNAME. SVar:TrigLose:DB$ LoseLife | LifeAmount$ 2 | SubAbility$ DBSac SVar:DBSac:DB$ Sacrifice | Amount$ 2 | SacValid$ Creature | SubAbility$ DBDraw diff --git a/forge-gui/res/cardsfolder/m/maddening_imp.txt b/forge-gui/res/cardsfolder/m/maddening_imp.txt index 867109d34b5..7606ed6ba7c 100644 --- a/forge-gui/res/cardsfolder/m/maddening_imp.txt +++ b/forge-gui/res/cardsfolder/m/maddening_imp.txt @@ -3,7 +3,7 @@ ManaCost:2 B Types:Creature Imp PT:1/1 K:Flying -A:AB$ PumpAll | Cost$ T | ValidCards$ Creature.ActivePlayerCtrl+nonWall | KW$ HIDDEN CARDNAME attacks each combat if able. | RememberAllPumped$ True | ActivationPhases$ Upkeep->Main1 | OpponentTurn$ True | SubAbility$ DelTrig | StackDescription$ SpellDescription | SpellDescription$ Non-Wall creatures the active player controls attack this turn if able. At the beginning of the next end step, destroy each of those creatures that didn't attack this turn. Activate only during an opponent's turn and only before combat. +A:AB$ PumpAll | Cost$ T | ValidCards$ Creature.ActivePlayerCtrl+nonWall | KW$ HIDDEN CARDNAME attacks each combat if able. | RememberAllPumped$ True | ActivationPhases$ Upkeep->Main1 | ActivationFirstCombat$ True | OpponentTurn$ True | SubAbility$ DelTrig | StackDescription$ SpellDescription | SpellDescription$ Non-Wall creatures the active player controls attack this turn if able. At the beginning of the next end step, destroy each of those creatures that didn't attack this turn. Activate only during an opponent's turn and only before combat. SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigDestroy | RememberObjects$ Remembered | SubAbility$ DBCleanup | TriggerDescription$ At the beginning of the next end step, destroy each of those creatures that didn't attack this turn. SVar:TrigDestroy:DB$ DestroyAll | ValidCards$ Creature.IsTriggerRemembered+notAttackedThisTurn SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/m/maskwood_nexus.txt b/forge-gui/res/cardsfolder/m/maskwood_nexus.txt index 4ac42b50e8f..3cbad28a2bc 100644 --- a/forge-gui/res/cardsfolder/m/maskwood_nexus.txt +++ b/forge-gui/res/cardsfolder/m/maskwood_nexus.txt @@ -1,7 +1,7 @@ Name:Maskwood Nexus ManaCost:4 Types:Artifact -S:Mode$ Continuous | Affected$ Creature.YouCtrl | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | AddType$ AllCreatureTypes & Creature | Description$ Creatures you control are every creature type. The same is true for creature spells you control and creature cards you own that aren't on the battlefield. +S:Mode$ Continuous | Affected$ Creature.YouCtrl | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | AddAllCreatureTypes$ True | Description$ Creatures you control are every creature type. The same is true for creature spells you control and creature cards you own that aren't on the battlefield. A:AB$ Token | Cost$ 3 T | LegacyImage$ u 2 2 shapeshifter changeling khm | TokenAmount$ 1 | TokenScript$ u_2_2_shapeshifter_changeling | TokenOwner$ You | SpellDescription$ Create a 2/2 blue Shapeshifter creature token with changeling. (It is every creature type.) DeckHas:Ability$Token Oracle:Creatures you control are every creature type. The same is true for creature spells you control and creature cards you own that aren't on the battlefield.\n{3}, {T}: Create a 2/2 blue Shapeshifter creature token with changeling. (It is every creature type.) diff --git a/forge-gui/res/cardsfolder/m/master_warcraft.txt b/forge-gui/res/cardsfolder/m/master_warcraft.txt index 50a24e0b6cf..a6b53983aeb 100644 --- a/forge-gui/res/cardsfolder/m/master_warcraft.txt +++ b/forge-gui/res/cardsfolder/m/master_warcraft.txt @@ -1,7 +1,7 @@ Name:Master Warcraft ManaCost:2 RW RW Types:Instant -A:SP$ DeclareCombatants | Cost$ 2 RW RW | DeclareAttackers$ True | DeclareBlockers$ True | ActivationPhases$ Upkeep->BeginCombat | Until$ EndOfTurn | SpellDescription$ Cast this spell only before attackers are declared. You choose which creatures attack this turn. You choose which creatures block this turn and how those creatures block. +A:SP$ DeclareCombatants | Cost$ 2 RW RW | DeclareAttackers$ True | DeclareBlockers$ True | ActivationPhases$ Upkeep->BeginCombat | ActivationFirstCombat$ True | Until$ EndOfTurn | SpellDescription$ Cast this spell only before attackers are declared. You choose which creatures attack this turn. You choose which creatures block this turn and how those creatures block. AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/master_warcraft.jpg Oracle:Cast this spell only before attackers are declared.\nYou choose which creatures attack this turn.\nYou choose which creatures block this turn and how those creatures block. diff --git a/forge-gui/res/cardsfolder/m/mercurial_transformation.txt b/forge-gui/res/cardsfolder/m/mercurial_transformation.txt index 7229fe9ed40..1d4dafb6902 100644 --- a/forge-gui/res/cardsfolder/m/mercurial_transformation.txt +++ b/forge-gui/res/cardsfolder/m/mercurial_transformation.txt @@ -3,6 +3,6 @@ ManaCost:1 U Types:Sorcery Lesson A:SP$ Animate | Cost$ 1 U | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | RemoveAllAbilities$ True | SubAbility$ DBChoose | SpellDescription$ Until end of turn, target nonland permanent loses all abilities and becomes your choice of a blue Frog creature with base power and toughness 1/1 or a blue Octopus creature with base power and toughness 4/4. SVar:DBChoose:DB$ GenericChoice | Defined$ You | Choices$ DBFrog,DBOctopus | StackDescription$ None -SVar:DBFrog:DB$ Animate | Power$ 1 | Toughness$ 1 | Colors$ Blue | OverwriteColors$ True | Types$ Creature,Frog | RemoveCardTypes$ True | RemoveSubTypes$ True | IsCurse$ True | Defined$ Targeted | SpellDescription$ Until end of turn, target nonland permanent loses all abilities and becomes a blue Frog with base power and toughness 1/1. -SVar:DBOctopus:DB$ Animate | Power$ 4 | Toughness$ 4 | Colors$ Blue | OverwriteColors$ True | Types$ Creature,Octopus | RemoveCardTypes$ True | RemoveSubTypes$ True | IsCurse$ True | Defined$ Targeted | SpellDescription$ Until end of turn, target nonland permanent loses all abilities and becomes a blue Octopus with base power and toughness 4/4. +SVar:DBFrog:DB$ Animate | Power$ 1 | Toughness$ 1 | Colors$ Blue | OverwriteColors$ True | Types$ Creature,Frog | RemoveCardTypes$ True | RemoveCreatureTypes$ True | IsCurse$ True | Defined$ Targeted | SpellDescription$ Until end of turn, target nonland permanent loses all abilities and becomes a blue Frog with base power and toughness 1/1. +SVar:DBOctopus:DB$ Animate | Power$ 4 | Toughness$ 4 | Colors$ Blue | OverwriteColors$ True | Types$ Creature,Octopus | RemoveCardTypes$ True | RemoveCreatureTypes$ True | IsCurse$ True | Defined$ Targeted | SpellDescription$ Until end of turn, target nonland permanent loses all abilities and becomes a blue Octopus with base power and toughness 4/4. Oracle:Until end of turn, target nonland permanent loses all abilities and becomes your choice of a blue Frog creature with base power and toughness 1/1 or a blue Octopus creature with base power and toughness 4/4. diff --git a/forge-gui/res/cardsfolder/m/mindblaze.txt b/forge-gui/res/cardsfolder/m/mindblaze.txt index ec564b4f87e..fe089006aa1 100644 --- a/forge-gui/res/cardsfolder/m/mindblaze.txt +++ b/forge-gui/res/cardsfolder/m/mindblaze.txt @@ -9,7 +9,7 @@ SVar:DBShuffle:DB$ Shuffle | Defined$ ParentTarget | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:TargetedPlayer$CardsInLibrary SVar:Y:Remembered$Valid Card.NamedCard -SVar:Z:Number$ChosenNumber +SVar:Z:Count$ChosenNumber AI:RemoveDeck:All AI:RemoveDeck:Random SVar:Picture:http://www.wizards.com/global/images/magic/general/mindblaze.jpg diff --git a/forge-gui/res/cardsfolder/m/mirror_entity.txt b/forge-gui/res/cardsfolder/m/mirror_entity.txt index 664130c75ac..d18f81c29e5 100644 --- a/forge-gui/res/cardsfolder/m/mirror_entity.txt +++ b/forge-gui/res/cardsfolder/m/mirror_entity.txt @@ -3,8 +3,7 @@ ManaCost:2 W Types:Creature Shapeshifter PT:1/1 K:Changeling -A:AB$ AnimateAll | Cost$ X | Power$ X | Toughness$ X | Types$ AllCreatureTypes | ValidCards$ Creature.YouCtrl | SpellDescription$ Until end of turn, creatures you control have base power and toughness X/X and gain all creature types. | StackDescription$ SpellDescription +A:AB$ AnimateAll | Cost$ X | Power$ X | Toughness$ X | AddAllCreatureTypes$ True | ValidCards$ Creature.YouCtrl | SpellDescription$ Until end of turn, creatures you control have base power and toughness X/X and gain all creature types. | StackDescription$ SpellDescription SVar:X:Count$xPaid AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/mirror_entity.jpg Oracle:Changeling (This card is every creature type.)\n{X}: Until end of turn, creatures you control have base power and toughness X/X and gain all creature types. diff --git a/forge-gui/res/cardsfolder/m/mirror_entity_avatar.txt b/forge-gui/res/cardsfolder/m/mirror_entity_avatar.txt index 9b6eecb54b3..67b3ce11794 100644 --- a/forge-gui/res/cardsfolder/m/mirror_entity_avatar.txt +++ b/forge-gui/res/cardsfolder/m/mirror_entity_avatar.txt @@ -3,7 +3,6 @@ ManaCost:no cost Types:Vanguard HandLifeModifier:+1/-2 A:AB$ ChooseType | ActivationZone$ Command | Cost$ X | Defined$ You | Type$ Creature | AILogic$ MostProminentComputerControls | SubAbility$ DBAnimate | SpellDescription$ Choose a creature type. Until end of turn, creatures you control of the chosen type have base power and toughness X/X and gain all creature types. -SVar:DBAnimate:DB$ AnimateAll | Power$ X | Toughness$ X | Types$ AllCreatureTypes | ValidCards$ Creature.YouCtrl+ChosenType +SVar:DBAnimate:DB$ AnimateAll | Power$ X | Toughness$ X | AddAllCreatureTypes$ True | ValidCards$ Creature.YouCtrl+ChosenType SVar:X:Count$xPaid -SVar:Picture:https://downloads.cardforge.org/images/cards/VAN/Mirror Entity Avatar.full.jpg Oracle:Hand +1, life -2\n{X}: Choose a creature type. Until end of turn, creatures you control of the chosen type have base power and toughness X/X and gain all creature types. diff --git a/forge-gui/res/cardsfolder/m/mistform_ultimus.txt b/forge-gui/res/cardsfolder/m/mistform_ultimus.txt index 0439013d4b6..d09bb52ab55 100644 --- a/forge-gui/res/cardsfolder/m/mistform_ultimus.txt +++ b/forge-gui/res/cardsfolder/m/mistform_ultimus.txt @@ -2,6 +2,5 @@ Name:Mistform Ultimus ManaCost:3 U Types:Legendary Creature Illusion PT:3/3 -S:Mode$ Continuous | Affected$ Card.Self | EffectZone$ All | CharacteristicDefining$ True | AddType$ AllCreatureTypes | Description$ CARDNAME is every creature type (even if this card isn't on the battlefield). -SVar:Picture:http://www.wizards.com/global/images/magic/general/mistform_ultimus.jpg +S:Mode$ Continuous | Affected$ Card.Self | EffectZone$ All | CharacteristicDefining$ True | AddAllCreatureTypes$ True | Description$ CARDNAME is every creature type (even if this card isn't on the battlefield). Oracle:Mistform Ultimus is every creature type (even if this card isn't on the battlefield). diff --git a/forge-gui/res/cardsfolder/m/moraug_fury_of_akoum.txt b/forge-gui/res/cardsfolder/m/moraug_fury_of_akoum.txt index 105983e0e91..c26b816da3f 100644 --- a/forge-gui/res/cardsfolder/m/moraug_fury_of_akoum.txt +++ b/forge-gui/res/cardsfolder/m/moraug_fury_of_akoum.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Minotaur Warrior PT:6/6 S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddPower$ AffectedX | Description$ Each creature you control gets +1/+0 for each time it has attacked this turn. SVar:AffectedX:Count$CardNumAttacksThisTurn -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | PlayerTurn$ True | Phase$ Main1,Main2 | Execute$ TrigAddPhase | TriggerDescription$ Landfall - Whenever a land enters the battlefield under your control, if it's your main phase, there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | AILogic$ SafeToHold | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | PlayerTurn$ True | Phase$ Main1,Main2 | Execute$ TrigAddPhase | TriggerDescription$ Landfall - Whenever a land enters the battlefield under your control, if it's your main phase, there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control. SVar:TrigAddPhase:DB$ AddPhase | ExtraPhase$ Combat | ConditionPhases$ Main1,Main2 | ExtraPhaseDelayedTrigger$ DelTrigUntap | ExtraPhaseDelayedTriggerExcute$ TrigUntapAll SVar:DelTrigUntap:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerDescription$ At the beginning of that combat, untap all creatures you control. SVar:TrigUntapAll:DB$ UntapAll | ValidCards$ Creature.YouCtrl diff --git a/forge-gui/res/cardsfolder/m/mutavault.txt b/forge-gui/res/cardsfolder/m/mutavault.txt index 0b7ba92fa73..b98c0313fa2 100644 --- a/forge-gui/res/cardsfolder/m/mutavault.txt +++ b/forge-gui/res/cardsfolder/m/mutavault.txt @@ -2,6 +2,5 @@ Name:Mutavault ManaCost:no cost Types:Land A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. -A:AB$ Animate | Cost$ 1 | Defined$ Self | Power$ 2 | Toughness$ 2 | Types$ Creature,AllCreatureTypes | SpellDescription$ CARDNAME becomes a 2/2 creature with all creature types until end of turn. It's still a land. -SVar:Picture:http://www.wizards.com/global/images/magic/general/mutavault.jpg +A:AB$ Animate | Cost$ 1 | Defined$ Self | Power$ 2 | Toughness$ 2 | Types$ Creature | AddAllCreatureTypes$ True | SpellDescription$ CARDNAME becomes a 2/2 creature with all creature types until end of turn. It's still a land. Oracle:{T}: Add {C}.\n{1}: Mutavault becomes a 2/2 creature with all creature types until end of turn. It's still a land. diff --git a/forge-gui/res/cardsfolder/m/muzzio_visionary_architect.txt b/forge-gui/res/cardsfolder/m/muzzio_visionary_architect.txt index 7be8233860c..895713e74bd 100644 --- a/forge-gui/res/cardsfolder/m/muzzio_visionary_architect.txt +++ b/forge-gui/res/cardsfolder/m/muzzio_visionary_architect.txt @@ -2,7 +2,7 @@ Name:Muzzio, Visionary Architect ManaCost:1 U U Types:Legendary Creature Human Artificer PT:1/3 -A:AB$ Dig | Cost$ 3 U T | DigNum$ X | Optional$ True | ChangeValid$ Artifact | DestinationZone$ Battlefield | AILogic$ AtOppEndOfTurn | SpellDescription$ Look at the top X cards of your library, where X is the highest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order. +A:AB$ Dig | Cost$ 3 U T | DigNum$ X | Optional$ True | ChangeValid$ Artifact | DestinationZone$ Battlefield | AILogic$ AtOppEOT | SpellDescription$ Look at the top X cards of your library, where X is the highest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order. SVar:X:Count$HighestCMC_Artifact.YouCtrl+inZoneBattlefield SVar:Picture:http://www.wizards.com/global/images/magic/general/muzzio_visionary_architect.jpg Oracle:{3}{U}, {T}: Look at the top X cards of your library, where X is the highest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order. diff --git a/forge-gui/res/cardsfolder/m/mystic_archaeologist.txt b/forge-gui/res/cardsfolder/m/mystic_archaeologist.txt index 4bf64a9b5d0..190459817c9 100644 --- a/forge-gui/res/cardsfolder/m/mystic_archaeologist.txt +++ b/forge-gui/res/cardsfolder/m/mystic_archaeologist.txt @@ -1,6 +1,6 @@ Name:Mystic Archaeologist ManaCost:1 U Types:Creature Human Wizard -A:AB$ Draw | Cost$ 3 U U | Defined$ You | NumCards$ 2 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw two cards. +A:AB$ Draw | Cost$ 3 U U | Defined$ You | NumCards$ 2 | AILogic$ AtOppEOT | SpellDescription$ Draw two cards. Oracle:{3}{U}{U}: Draw two cards. PT:2/1 diff --git a/forge-gui/res/cardsfolder/n/nebelgast_beguiler.txt b/forge-gui/res/cardsfolder/n/nebelgast_beguiler.txt index 5d7698fe993..932077c8d95 100644 --- a/forge-gui/res/cardsfolder/n/nebelgast_beguiler.txt +++ b/forge-gui/res/cardsfolder/n/nebelgast_beguiler.txt @@ -2,7 +2,6 @@ Name:Nebelgast Beguiler ManaCost:4 W Types:Creature Spirit PT:2/5 -K:Flying A:AB$ Tap | Cost$ W T | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Tap target creature. SVar:NonCombatPriority:1 Oracle:Flying\n{W}, {T}: Tap target creature. diff --git a/forge-gui/res/cardsfolder/n/niko_aris.txt b/forge-gui/res/cardsfolder/n/niko_aris.txt index eb9bcf57ed2..5edcef06271 100644 --- a/forge-gui/res/cardsfolder/n/niko_aris.txt +++ b/forge-gui/res/cardsfolder/n/niko_aris.txt @@ -3,7 +3,7 @@ ManaCost:X W U U Types:Legendary Planeswalker Niko Loyalty:3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create X Shard tokens. (They're enchantments with "{2}, Sacrifice this enchantment: Scry 1, then draw a card.") -SVar:TrigToken:DB$ Token | TokenAmount$ X | TokenScript$ shard | TokenOwner$ You +SVar:TrigToken:DB$ Token | TokenAmount$ X | TokenScript$ c_e_shard_draw | TokenOwner$ You SVar:X:Count$xPaid A:AB$ Effect | Cost$ AddCounter<1/LOYALTY> | Name$ Niko Aris Effect | Planeswalker$ True | Triggers$ Trig | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | RememberObjects$ Targeted | SubAbility$ DBPump | SpellDescription$ Up to one target creature you control can't be blocked this turn. Whenever that creature deals damage this turn, return it to its owner's hand. SVar:DBPump:DB$ Pump | KW$ HIDDEN Unblockable | Defined$ Targeted @@ -11,6 +11,6 @@ SVar:Trig:Mode$ DamageDealtOnce | ValidSource$ Creature.IsRemembered | Execute$ SVar:Eff:DB$ ChangeZone | ValidTgts$ Creature.IsRemembered | Origin$ Battlefield | Destination$ Hand A:AB$ DealDamage | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature.tapped | NumDmg$ Y | TgtPrompt$ Select target tapped creature | SpellDescription$ CARDNAME deals 2 damage to target tapped creature for each card you've drawn this turn. SVar:Y:Count$YouDrewThisTurn/Twice -A:AB$ Token | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenScript$ shard | TokenOwner$ You | SpellDescription$ Create a Shard token. +A:AB$ Token | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenScript$ c_e_shard_draw | TokenOwner$ You | SpellDescription$ Create a Shard token. DeckHas:Ability$Token & Ability$Sacrifice Oracle:When Niko Aris enters the battlefield, create X Shard tokens. (They're enchantments with "{2}, Sacrifice this enchantment: Scry 1, then draw a card.")\n[+1]: Up to one target creature you control can't be blocked this turn. Whenever that creature deals damage this turn, return it to its owner's hand.\n[−1]: Niko Aris deals 2 damage to target tapped creature for each card you've drawn this turn.\n[−1]: Create a Shard token. diff --git a/forge-gui/res/cardsfolder/n/niv_mizzet_the_firemind.txt b/forge-gui/res/cardsfolder/n/niv_mizzet_the_firemind.txt index 87f848d8433..8e87244e1b5 100644 --- a/forge-gui/res/cardsfolder/n/niv_mizzet_the_firemind.txt +++ b/forge-gui/res/cardsfolder/n/niv_mizzet_the_firemind.txt @@ -3,7 +3,7 @@ ManaCost:2 U U R R Types:Legendary Creature Dragon Wizard PT:4/4 K:Flying -A:AB$ Draw | Cost$ T | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. +A:AB$ Draw | Cost$ T | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card. T:Mode$ Drawn | ValidCard$ Card.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigDealDamage | TriggerDescription$ Whenever you draw a card, CARDNAME deals 1 damage to any target. SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 SVar:Picture:http://www.wizards.com/global/images/magic/general/niv_mizzet_the_firemind.jpg diff --git a/forge-gui/res/cardsfolder/n/norritt.txt b/forge-gui/res/cardsfolder/n/norritt.txt index 4f9652cbb47..447cf329afb 100644 --- a/forge-gui/res/cardsfolder/n/norritt.txt +++ b/forge-gui/res/cardsfolder/n/norritt.txt @@ -3,7 +3,7 @@ ManaCost:3 B Types:Creature Imp PT:1/1 A:AB$ Untap | Cost$ T | ValidTgts$ Creature.Blue | TgtPrompt$ Select target blue creature | SpellDescription$ Untap target blue creature. -A:AB$ Pump | Cost$ T | ValidTgts$ Creature.nonWall+ActivePlayerCtrl+notFirstTurnControlled | TgtPrompt$ Select target non-Wall creature the active player has controlled continuously since the beginning of the turn. | ActivationPhases$ Upkeep->BeginCombat | KW$ HIDDEN CARDNAME attacks each combat if able. | SubAbility$ DestroyPacifist | SpellDescription$ Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That creature attacks this turn if able. Destroy it at the beginning of the next end step if it didn't attack this turn. Activate only before attackers are declared. +A:AB$ Pump | Cost$ T | ValidTgts$ Creature.nonWall+ActivePlayerCtrl+notFirstTurnControlled | TgtPrompt$ Select target non-Wall creature the active player has controlled continuously since the beginning of the turn. | ActivationPhases$ Upkeep->BeginCombat | ActivationFirstCombat$ True | KW$ HIDDEN CARDNAME attacks each combat if able. | SubAbility$ DestroyPacifist | SpellDescription$ Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That creature attacks this turn if able. Destroy it at the beginning of the next end step if it didn't attack this turn. Activate only before attackers are declared. SVar:DestroyPacifist:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigDestroy | RememberObjects$ ParentTarget | TriggerDescription$ At the beginning of the end step, destroy that creature if it didn't attack this turn. SVar:TrigDestroy:DB$ Destroy | Defined$ DelayTriggerRemembered | ConditionDefined$ DelayTriggerRemembered | ConditionPresent$ Creature.notAttackedThisTurn | ConditionCompare$ GE1 AI:RemoveDeck:All diff --git a/forge-gui/res/cardsfolder/o/omnath_locus_of_mana.txt b/forge-gui/res/cardsfolder/o/omnath_locus_of_mana.txt index 8696f7846d6..e5ebdb6a8eb 100644 --- a/forge-gui/res/cardsfolder/o/omnath_locus_of_mana.txt +++ b/forge-gui/res/cardsfolder/o/omnath_locus_of_mana.txt @@ -2,7 +2,7 @@ Name:Omnath, Locus of Mana ManaCost:2 G Types:Legendary Creature Elemental PT:1/1 -S:Mode$ Continuous | Affected$ You | AddKeyword$ Green mana doesn't empty from your mana pool as steps and phases end. | Description$ You don't lose unspent green mana as steps and phases end. +S:Mode$ UnspentMana | ValidPlayer$ You | ManaType$ Green | Description$ You don't lose unspent green mana as steps and phases end. S:Mode$ Continuous | Affected$ Card.Self | AddPower$ X | AddToughness$ X | Description$ CARDNAME gets +1/+1 for each unspent green mana you have. SVar:X:Count$ManaPool:green AI:RemoveDeck:All diff --git a/forge-gui/res/cardsfolder/o/overwhelming_splendor.txt b/forge-gui/res/cardsfolder/o/overwhelming_splendor.txt index ea40f6a6b28..2cf4a733c5c 100644 --- a/forge-gui/res/cardsfolder/o/overwhelming_splendor.txt +++ b/forge-gui/res/cardsfolder/o/overwhelming_splendor.txt @@ -4,6 +4,6 @@ Types:Enchantment Aura Curse K:Enchant player A:SP$ Attach | Cost$ 6 W W | ValidTgts$ Player | AILogic$ Curse S:Mode$ Continuous | Affected$ Creature.EnchantedPlayerCtrl | SetPower$ 1 | SetToughness$ 1 | RemoveAllAbilities$ True | Description$ Creatures enchanted player controls lose all abilities and have base power and toughness 1/1. -S:Mode$ CantBeActivated | Activator$ Player.EnchantedBy | NonMana$ True | NonLoyalty$ True | Description$ Enchanted player can't activate abilities that aren't mana abilities or loyalty abilities. +S:Mode$ CantBeActivated | Activator$ Player.EnchantedBy | ValidSA$ Activated.nonManaAbility+nonLoyalty | Description$ Enchanted player can't activate abilities that aren't mana abilities or loyalty abilities. SVar:Picture:http://www.wizards.com/global/images/magic/general/overwhelming_splendor.jpg Oracle:Enchant player\nCreatures enchanted player controls lose all abilities and have base power and toughness 1/1.\nEnchanted player can't activate abilities that aren't mana abilities or loyalty abilities. diff --git a/forge-gui/res/cardsfolder/p/pause_for_reflection.txt b/forge-gui/res/cardsfolder/p/pause_for_reflection.txt index a70e44267fb..8cd86cb8d8f 100644 --- a/forge-gui/res/cardsfolder/p/pause_for_reflection.txt +++ b/forge-gui/res/cardsfolder/p/pause_for_reflection.txt @@ -2,5 +2,5 @@ Name:Pause for Reflection ManaCost:2 G Types:Instant K:Convoke -A:SP$ Fog | Cost$ 2 G | SpellDescription$ CARDNAME deals all combat damage that would be dealt this turn. +A:SP$ Fog | Cost$ 2 G | SpellDescription$ Prevent all combat damage that would be dealt this turn. Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)\nPrevent all combat damage that would be dealt this turn. diff --git a/forge-gui/res/cardsfolder/p/pithing_needle.txt b/forge-gui/res/cardsfolder/p/pithing_needle.txt index 09ddf2c9f01..3f4e390b81b 100644 --- a/forge-gui/res/cardsfolder/p/pithing_needle.txt +++ b/forge-gui/res/cardsfolder/p/pithing_needle.txt @@ -3,7 +3,7 @@ ManaCost:1 Types:Artifact K:ETBReplacement:Other:DBNameCard SVar:DBNameCard:DB$ NameCard | Defined$ You | SpellDescription$ As CARDNAME enters the battlefield, choose a card name. -S:Mode$ CantBeActivated | ValidCard$ Card.NamedCard | NonMana$ True | Description$ Activated abilities of sources with the chosen name can't be activated unless they're mana abilities. +S:Mode$ CantBeActivated | ValidCard$ Card.NamedCard | ValidSA$ Activated.nonManaAbility | Description$ Activated abilities of sources with the chosen name can't be activated unless they're mana abilities. AI:RemoveDeck:Random SVar:Picture:http://www.wizards.com/global/images/magic/general/pithing_needle.jpg Oracle:As Pithing Needle enters the battlefield, choose a card name.\nActivated abilities of sources with the chosen name can't be activated unless they're mana abilities. diff --git a/forge-gui/res/cardsfolder/p/platinum_emperion.txt b/forge-gui/res/cardsfolder/p/platinum_emperion.txt index 5dc1097b470..ff194483dda 100644 --- a/forge-gui/res/cardsfolder/p/platinum_emperion.txt +++ b/forge-gui/res/cardsfolder/p/platinum_emperion.txt @@ -2,6 +2,5 @@ Name:Platinum Emperion ManaCost:8 Types:Artifact Creature Golem PT:8/8 -S:Mode$ Continuous | Affected$ You | AddKeyword$ Your life total can't change. | Description$ Your life total can't change. (You can't gain or lose life. You can't pay any amount of life except 0.) -SVar:Picture:http://www.wizards.com/global/images/magic/general/platinum_emperion.jpg +S:Mode$ CantChangeLife | ValidPlayer$ You | Description$ Your life total can't change. (You can't gain or lose life. You can't pay any amount of life except 0.) Oracle:Your life total can't change. (You can't gain or lose life. You can't pay any amount of life except 0.) diff --git a/forge-gui/res/cardsfolder/p/pristine_talisman.txt b/forge-gui/res/cardsfolder/p/pristine_talisman.txt index 0468d2739dd..d14cfd0f7d2 100644 --- a/forge-gui/res/cardsfolder/p/pristine_talisman.txt +++ b/forge-gui/res/cardsfolder/p/pristine_talisman.txt @@ -1,7 +1,7 @@ Name:Pristine Talisman ManaCost:3 Types:Artifact -A:AB$ Mana | Cost$ T | Produced$ C | SubAbility$ DBGainLife | SpellDescription$ Add {C}. You gain 1 life. +A:AB$ Mana | Cost$ T | Produced$ C | SubAbility$ DBGainLife | AILogic$ AtOppEOT | SpellDescription$ Add {C}. You gain 1 life. SVar:DBGainLife:DB$ GainLife | LifeAmount$ 1 | Defined$ You SVar:Picture:http://www.wizards.com/global/images/magic/general/pristine_talisman.jpg Oracle:{T}: Add {C}. You gain 1 life. diff --git a/forge-gui/res/cardsfolder/q/quakebringer.txt b/forge-gui/res/cardsfolder/q/quakebringer.txt index 7f3a6f1e940..581c0210122 100644 --- a/forge-gui/res/cardsfolder/q/quakebringer.txt +++ b/forge-gui/res/cardsfolder/q/quakebringer.txt @@ -2,7 +2,7 @@ Name:Quakebringer ManaCost:3 R R Types:Creature Giant Berserker PT:5/4 -S:Mode$ Continuous | Affected$ Player.Opponent | AddKeyword$ You can't gain life. | Description$ Your opponents can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Player.Opponent | Description$ Your opponents can't gain life. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDealDamage | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 2 damage to each opponent. This ability triggers only if CARDNAME is on the battlefield or if CARDNAME is in your graveyard and you control a Giant. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Graveyard | IsPresent$ Creature.YouCtrl+Giant | Execute$ TrigDealDamage | Secondary$ True | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 2 damage to each opponent. This ability triggers only if CARDNAME is on the battlefield or if CARDNAME is in your graveyard and you control a Giant. SVar:TrigDealDamage:DB$ DealDamage | NumDmg$ 2 | Defined$ Player.Opponent diff --git a/forge-gui/res/cardsfolder/r/rampaging_ferocidon.txt b/forge-gui/res/cardsfolder/r/rampaging_ferocidon.txt index 3e737fdb013..933fdedfd93 100644 --- a/forge-gui/res/cardsfolder/r/rampaging_ferocidon.txt +++ b/forge-gui/res/cardsfolder/r/rampaging_ferocidon.txt @@ -3,8 +3,7 @@ ManaCost:2 R Types:Creature Dinosaur PT:3/3 K:Menace -S:Mode$ Continuous | Affected$ Player | AddKeyword$ You can't gain life. | Description$ Players can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Player | Description$ Players can't gain life. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Other | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ Whenever another creature enters the battlefield, CARDNAME deals 1 damage to that creature's controller. SVar:TrigDamage:DB$ DealDamage | Defined$ TriggeredCardController | NumDmg$ 1 -SVar:Picture:http://mythicspoiler.com/ixa/cards/rampagingferocidon.jpg Oracle:Menace\nPlayers can't gain life.\nWhenever another creature enters the battlefield, Rampaging Ferocidon deals 1 damage to that creature's controller. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/r/rapid_fire.txt b/forge-gui/res/cardsfolder/r/rapid_fire.txt index cff71ac7963..d901949751c 100644 --- a/forge-gui/res/cardsfolder/r/rapid_fire.txt +++ b/forge-gui/res/cardsfolder/r/rapid_fire.txt @@ -2,7 +2,7 @@ Name:Rapid Fire ManaCost:3 W Types:Instant Text:Cast this spell only before blockers are declared. -A:SP$ Pump | Cost$ 3 W | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ First Strike | ActivationPhases$ Upkeep->Declare Attackers | SubAbility$ DBPump | SpellDescription$ Target creature gains first strike until end of turn. If it doesn't have rampage, that creature gains rampage 2 until end of turn. (Whenever the creature becomes blocked, it gets +2/+2 until end of turn for each creature blocking it beyond the first.) +A:SP$ Pump | Cost$ 3 W | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ First Strike | ActivationPhases$ Upkeep->Declare Attackers | ActivationFirstCombat$ True | SubAbility$ DBPump | SpellDescription$ Target creature gains first strike until end of turn. If it doesn't have rampage, that creature gains rampage 2 until end of turn. (Whenever the creature becomes blocked, it gets +2/+2 until end of turn for each creature blocking it beyond the first.) SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ Rampage:2 | ConditionDefined$ Targeted | ConditionPresent$ Creature.withoutRampage AI:RemoveDeck:All Oracle:Cast this spell only before blockers are declared.\nTarget creature gains first strike until end of turn. If it doesn't have rampage, that creature gains rampage 2 until end of turn. (Whenever the creature becomes blocked, it gets +2/+2 until end of turn for each creature blocking it beyond the first.) diff --git a/forge-gui/res/cardsfolder/r/roiling_vortex.txt b/forge-gui/res/cardsfolder/r/roiling_vortex.txt index 9954c413a40..348beb6283d 100755 --- a/forge-gui/res/cardsfolder/r/roiling_vortex.txt +++ b/forge-gui/res/cardsfolder/r/roiling_vortex.txt @@ -5,5 +5,6 @@ T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | Execute$ Trig1Damage | Tri SVar:Trig1Damage:DB$ DealDamage | Defined$ TriggeredPlayer | NumDmg$ 1 T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Player | TriggerZones$ Battlefield | Execute$ Trig5Damage | HasNoManaCost$ True | TriggerDescription$ Whenever a player casts a spell, if no mana was spent to cast that spell, CARDNAME deals 5 damage to that player. SVar:Trig5Damage:DB$ DealDamage | Defined$ TriggeredCardController | NumDmg$ 5 -A:AB$ Pump | Cost$ R | KW$ You can't gain life. | Defined$ Player.Opponent | StackDescription$ SpellDescription | SpellDescription$ Your opponents can't gain life this turn. +A:AB$ Effect | Cost$ R | Name$ Atarka's Command Effect | StaticAbilities$ STCantGain | AILogic$ NoGain | SpellDescription$ Your opponents can't gain life this turn. +SVar:STCantGain:Mode$ CantGainLife | ValidPlayer$ Player.Opponent | Description$ Your opponents can't gain life this turn. Oracle:At the beginning of each player's upkeep, Roiling Vortex deals 1 damage to them.\nWhenever a player casts a spell, if no mana was spent to cast that spell, Roiling Vortex deals 5 damage to that player.\n{R}: Your opponents can't gain life this turn. diff --git a/forge-gui/res/cardsfolder/r/runed_stalactite.txt b/forge-gui/res/cardsfolder/r/runed_stalactite.txt index ed0b4ed416f..fd51992e3c4 100644 --- a/forge-gui/res/cardsfolder/r/runed_stalactite.txt +++ b/forge-gui/res/cardsfolder/r/runed_stalactite.txt @@ -1,7 +1,6 @@ Name:Runed Stalactite ManaCost:1 Types:Artifact Equipment -S:Mode$ Continuous | Affected$ Card.EquippedBy | AddPower$ 1 | AddToughness$ 1 | AddType$ AllCreatureTypes | Description$ Equipped creature gets +1/+1 and is every creature type. +S:Mode$ Continuous | Affected$ Card.EquippedBy | AddPower$ 1 | AddToughness$ 1 | AddAllCreatureTypes$ True | Description$ Equipped creature gets +1/+1 and is every creature type. K:Equip:2 -SVar:Picture:http://www.wizards.com/global/images/magic/general/runed_stalactite.jpg Oracle:Equipped creature gets +1/+1 and is every creature type.\nEquip {2} diff --git a/forge-gui/res/cardsfolder/s/sanctum_prelate.txt b/forge-gui/res/cardsfolder/s/sanctum_prelate.txt index 42b01216808..f6790b0a40d 100644 --- a/forge-gui/res/cardsfolder/s/sanctum_prelate.txt +++ b/forge-gui/res/cardsfolder/s/sanctum_prelate.txt @@ -5,7 +5,7 @@ PT:2/2 K:ETBReplacement:Other:ChooseNumber SVar:ChooseNumber:DB$ ChooseNumber | Defined$ You | SpellDescription$ As CARDNAME enters the battlefield, choose a number. S:Mode$ CantBeCast | ValidCard$ Card.nonCreature+cmcEQX | Description$ Noncreature spells with mana value equal to the chosen number can't be cast. -SVar:X:Number$ChosenNumber +SVar:X:Count$ChosenNumber AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/sanctum_prelate.jpg Oracle:As Sanctum Prelate enters the battlefield, choose a number.\nNoncreature spells with mana value equal to the chosen number can't be cast. diff --git a/forge-gui/res/cardsfolder/s/senseis_divining_top.txt b/forge-gui/res/cardsfolder/s/senseis_divining_top.txt index 7da6b836d40..61d25f2af52 100644 --- a/forge-gui/res/cardsfolder/s/senseis_divining_top.txt +++ b/forge-gui/res/cardsfolder/s/senseis_divining_top.txt @@ -1,7 +1,7 @@ Name:Sensei's Divining Top ManaCost:1 Types:Artifact -A:AB$ RearrangeTopOfLibrary | Cost$ 1 | Defined$ You | NumCards$ 3 | AILogic$ EOTBeforeOwnTurn | AIRespondsToOwnAbility$ True | SpellDescription$ Look at the top three cards of your library, then put them back in any order. +A:AB$ RearrangeTopOfLibrary | Cost$ 1 | Defined$ You | NumCards$ 3 | AIRespondsToOwnAbility$ True | SpellDescription$ Look at the top three cards of your library, then put them back in any order. A:AB$ Draw | Cost$ T | Defined$ You | NumCards$ 1 | SubAbility$ DBChangeZone | AILogic$ RespondToOwnActivation | SpellDescription$ Draw a card, then put CARDNAME on top of its owner's library. SVar:DBChangeZone:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Library | LibraryPosition$ 0 SVar:Picture:http://www.wizards.com/global/images/magic/general/senseis_divining_top.jpg diff --git a/forge-gui/res/cardsfolder/s/serra_bestiary.txt b/forge-gui/res/cardsfolder/s/serra_bestiary.txt index fe3fcd064ed..4f45a9b7b27 100644 --- a/forge-gui/res/cardsfolder/s/serra_bestiary.txt +++ b/forge-gui/res/cardsfolder/s/serra_bestiary.txt @@ -5,6 +5,6 @@ K:Enchant creature K:UpkeepCost:W W A:SP$ Attach | Cost$ W W | ValidTgts$ Creature | AILogic$ Curse S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddHiddenKeyword$ CARDNAME can't attack or block. | Description$ Enchanted creature can't attack or block, and its activated abilities with {T} in their costs can't be activated. -S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | TapAbility$ True +S:Mode$ CantBeActivated | ValidCard$ Card.EnchantedBy | ValidSA$ Activated.hasTapCost SVar:Picture:http://www.wizards.com/global/images/magic/general/serra_bestiary.jpg Oracle:Enchant creature\nAt the beginning of your upkeep, sacrifice Serra Bestiary unless you pay {W}{W}.\nEnchanted creature can't attack or block, and its activated abilities with {T} in their costs can't be activated. diff --git a/forge-gui/res/cardsfolder/s/shields_of_velis_vel.txt b/forge-gui/res/cardsfolder/s/shields_of_velis_vel.txt index fba57c89625..b6679843647 100644 --- a/forge-gui/res/cardsfolder/s/shields_of_velis_vel.txt +++ b/forge-gui/res/cardsfolder/s/shields_of_velis_vel.txt @@ -3,8 +3,7 @@ ManaCost:W Types:Tribal Instant Shapeshifter K:Changeling A:SP$ PumpAll | Cost$ W | ValidTgts$ Player | TgtPrompt$ Select target player | ValidCards$ Creature | NumAtt$ +0 | NumDef$ +1 | SubAbility$ DBAnimate | SpellDescription$ Creatures target player controls get +0/+1 and gain all creature types until end of turn. -SVar:DBAnimate:DB$ AnimateAll | ValidCards$ Creature.TargetedPlayerCtrl | Types$ AllCreatureTypes +SVar:DBAnimate:DB$ AnimateAll | ValidCards$ Creature.TargetedPlayerCtrl | AddAllCreatureTypes$ True SVar:NeedsToPlay:Creature.YouCtrl AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/shields_of_velis_vel.jpg Oracle:Changeling (This card is every creature type.)\nCreatures target player controls get +0/+1 and gain all creature types until end of turn. diff --git a/forge-gui/res/cardsfolder/s/skullcrack.txt b/forge-gui/res/cardsfolder/s/skullcrack.txt index 9d6e64ccfd5..8e44235459b 100644 --- a/forge-gui/res/cardsfolder/s/skullcrack.txt +++ b/forge-gui/res/cardsfolder/s/skullcrack.txt @@ -2,7 +2,7 @@ Name:Skullcrack ManaCost:1 R Types:Instant A:SP$ Effect | Cost$ 1 R | Name$ Skullcrack Effect | StaticAbilities$ STCantGain,STCantPrevent | AILogic$ Burn | SubAbility$ DBDamage | SpellDescription$ Players can't gain life this turn. Damage can't be prevented this turn. CARDNAME deals 3 damage to target player or planeswalker. -SVar:STCantGain:Mode$ Continuous | EffectZone$ Command | Affected$ Player | AddKeyword$ You can't gain life. | Description$ Players can't gain life. +SVar:STCantGain:Mode$ CantGainLife | ValidPlayer$ Player | Description$ Players can't gain life this turn. SVar:STCantPrevent:Mode$ CantPreventDamage | EffectZone$ Command | Description$ Damage can't be prevented. SVar:DBDamage:DB$ DealDamage | ValidTgts$ Player,Planeswalker | TgtPrompt$ Select target player or planeswalker | NumDmg$ 3 | NoPrevention$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/skullcrack.jpg diff --git a/forge-gui/res/cardsfolder/s/sorcerous_spyglass.txt b/forge-gui/res/cardsfolder/s/sorcerous_spyglass.txt index 0af77016b06..9487cf86b8f 100644 --- a/forge-gui/res/cardsfolder/s/sorcerous_spyglass.txt +++ b/forge-gui/res/cardsfolder/s/sorcerous_spyglass.txt @@ -6,7 +6,7 @@ SVar:ChoosePlayer:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | C SVar:DBLook:DB$ RevealHand | Defined$ ChosenPlayer | SubAbility$ DBNameCard SVar:DBNameCard:DB$ NameCard | Defined$ You | SubAbility$ DBClear SVar:DBClear:DB$ Cleanup | ClearChosenPlayer$ True -S:Mode$ CantBeActivated | ValidCard$ Card.NamedCard | NonMana$ True | Description$ Activated abilities of sources with the chosen name can't be activated unless they're mana abilities. +S:Mode$ CantBeActivated | ValidCard$ Card.NamedCard | ValidSA$ Activated.nonManaAbility | Description$ Activated abilities of sources with the chosen name can't be activated unless they're mana abilities. AI:RemoveDeck:Random # TODO: Might improve AI logic to support it (the AI needs to pick cards that actually have activated nonmana abilities on them) AI:RemoveDeck:All diff --git a/forge-gui/res/cardsfolder/s/sparring_regimen.txt b/forge-gui/res/cardsfolder/s/sparring_regimen.txt index 0f56e7ee597..a7d69f9fc8e 100644 --- a/forge-gui/res/cardsfolder/s/sparring_regimen.txt +++ b/forge-gui/res/cardsfolder/s/sparring_regimen.txt @@ -6,5 +6,6 @@ SVar:TrigLearn:DB$ Learn T:Mode$ AttackersDeclared | AttackingPlayer$ You | Execute$ TrigPutCounter | TriggerZones$ Battlefield | TriggerDescription$ Whenever you attack, put a +1/+1 counter on target attacking creature and untap it. SVar:TrigPutCounter:DB$ PutCounter | CounterType$ P1P1 | CounterNum$ 1 | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | SubAbility$ DBUntap SVar:DBUntap:DB$ Untap | Defined$ Targeted +SVar:PlayMain1:TRUE DeckHas:Ability$Counters Oracle:When Sparring Regimen enters the battlefield, learn. (You may reveal a Lesson card you own from outside the game and put it into your hand, or discard a card to draw a card.)\nWhenever you attack, put a +1/+1 counter on target attacking creature and untap it. diff --git a/forge-gui/res/cardsfolder/s/spectral_sailor.txt b/forge-gui/res/cardsfolder/s/spectral_sailor.txt index e045469fdca..9b252402aeb 100644 --- a/forge-gui/res/cardsfolder/s/spectral_sailor.txt +++ b/forge-gui/res/cardsfolder/s/spectral_sailor.txt @@ -4,5 +4,5 @@ Types:Creature Spirit Pirate PT:1/1 K:Flash K:Flying -A:AB$ Draw | Cost$ 3 U | NumCards$ 1 | Defined$ You | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. +A:AB$ Draw | Cost$ 3 U | NumCards$ 1 | Defined$ You | AILogic$ AtOppEOT | SpellDescription$ Draw a card. Oracle:Flash (You may cast this spell any time you could cast an instant.)\nFlying\n{3}{U}: Draw a card. diff --git a/forge-gui/res/cardsfolder/s/spinal_parasite.txt b/forge-gui/res/cardsfolder/s/spinal_parasite.txt index 1d3b3ebc5b7..1d910498dfe 100644 --- a/forge-gui/res/cardsfolder/s/spinal_parasite.txt +++ b/forge-gui/res/cardsfolder/s/spinal_parasite.txt @@ -4,8 +4,6 @@ Types:Artifact Creature Insect PT:-1/-1 K:Sunburst A:AB$ RemoveCounter | Cost$ SubCounter<2/P1P1> | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | CounterType$ Any | CounterNum$ 1 | SpellDescription$ Remove a counter from target permanent. -#TODO: For some reason the AI removes beneficial counters from its own permanents with this card. -AI:RemoveDeck:All AI:RemoveDeck:Random SVar:NeedsToPlayVar:Z GE3 SVar:NoZeroToughnessAI:True diff --git a/forge-gui/res/cardsfolder/s/squees_revenge.txt b/forge-gui/res/cardsfolder/s/squees_revenge.txt index b0a6633ee24..93a082646a4 100644 --- a/forge-gui/res/cardsfolder/s/squees_revenge.txt +++ b/forge-gui/res/cardsfolder/s/squees_revenge.txt @@ -10,7 +10,7 @@ SVar:IncrementLoss:DB$ StoreSVar | SVar$ Loss | Type$ CountSVar | Expression$ Lo SVar:SetFilpsDone:DB$ StoreSVar | SVar$ FlipsDone | Type$ CountSVar | Expression$ TimesToFlip # Draw Cards SVar:DrawIfWin:DB$ Draw | Defined$ You | NumCards$ CardsToDraw | ConditionCheckSVar$ Loss | ConditionSVarCompare$ EQ0 -SVar:TimesToFlip:Number$ChosenNumber +SVar:TimesToFlip:Count$ChosenNumber SVar:FlipsDone:Number$0 SVar:Loss:Number$0 SVar:CardsToDraw:Count$ChosenNumber/Times.2 diff --git a/forge-gui/res/cardsfolder/s/stigma_lasher.txt b/forge-gui/res/cardsfolder/s/stigma_lasher.txt index d9919d32819..1edd7966ef4 100644 --- a/forge-gui/res/cardsfolder/s/stigma_lasher.txt +++ b/forge-gui/res/cardsfolder/s/stigma_lasher.txt @@ -5,6 +5,5 @@ PT:2/2 K:Wither T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ TrigEffect | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals damage to a player, that player can't gain life for the rest of the game. SVar:TrigEffect:DB$ Effect | Name$ Stigma Lasher Effect | StaticAbilities$ CantGainLife | Duration$ Permanent | RememberObjects$ TriggeredTarget -SVar:CantGainLife:Mode$ Continuous | EffectZone$ Command | Affected$ Player.IsRemembered | AddKeyword$ You can't gain life. | Description$ The damaged player can't gain life for the rest of the game. -SVar:Picture:http://www.wizards.com/global/images/magic/general/stigma_lasher.jpg +SVar:CantGainLife:Mode$ CantGainLife | ValidPlayer$ Player.IsRemembered | Description$ The damaged player can't gain life for the rest of the game. Oracle:Wither (This deals damage to creatures in the form of -1/-1 counters.)\nWhenever Stigma Lasher deals damage to a player, that player can't gain life for the rest of the game. diff --git a/forge-gui/res/cardsfolder/s/strixhaven_stadium.txt b/forge-gui/res/cardsfolder/s/strixhaven_stadium.txt index e6e9130aea7..e73f2be1394 100644 --- a/forge-gui/res/cardsfolder/s/strixhaven_stadium.txt +++ b/forge-gui/res/cardsfolder/s/strixhaven_stadium.txt @@ -1,7 +1,7 @@ Name:Strixhaven Stadium ManaCost:3 Types:Artifact -A:AB$ Mana | Cost$ T | Produced$ C | SubAbility$ DBPutCounter | SpellDescription$ Add {C}. Put a point counter on CARDNAME. +A:AB$ Mana | Cost$ T | Produced$ C | SubAbility$ DBPutCounter | AILogic$ AtOppEOT | SpellDescription$ Add {C}. Put a point counter on CARDNAME. SVar:DBPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ POINT | CounterNum$ 1 T:Mode$ DamageDone | ValidSource$ Creature | ValidTarget$ You | CombatDamage$ True | Execute$ TrigRemove | TriggerZones$ Battlefield | TriggerDescription$ Whenever a creature deals combat damage to you, remove a point counter from CARDNAME. SVar:TrigRemove:DB$ RemoveCounter | Defined$ Self | CounterType$ POINT | CounterNum$ 1 diff --git a/forge-gui/res/cardsfolder/s/subtlety.txt b/forge-gui/res/cardsfolder/s/subtlety.txt index 175afc4a63f..81dc3ee21b7 100644 --- a/forge-gui/res/cardsfolder/s/subtlety.txt +++ b/forge-gui/res/cardsfolder/s/subtlety.txt @@ -5,6 +5,6 @@ PT:3/3 K:Flash K:Flying T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigTuck | TriggerDescription$ When CARDNAME enters the battlefield, choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library. -SVar:TrigTuck:DB$ ChangeZone | ValidTgts$ Card.inZoneStack+Creature,Card.inZoneStack+Planeswalker | TgtZone$ Stack | TgtPrompt$ Select up to one target creature spell or planeswalker spell | AlternativeDecider$ TargetedController | Origin$ Stack | Fizzle$ True | Destination$ Library | LibraryPosition$ 0 | DestinationAlternative$ Library | LibraryPositionAlternative$ -1 | AlternativeDestinationMessage$ Would you like to put the card on the top of your library (and not on the bottom)? | SpellDescription$ Choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library. +SVar:TrigTuck:DB$ ChangeZone | ValidTgts$ Card.inZoneStack+Creature,Card.inZoneStack+Planeswalker | TgtZone$ Stack | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target creature spell or planeswalker spell | AlternativeDecider$ TargetedController | Origin$ Stack | Fizzle$ True | Destination$ Library | LibraryPosition$ 0 | DestinationAlternative$ Library | LibraryPositionAlternative$ -1 | AlternativeDestinationMessage$ Would you like to put the card on the top of your library (and not on the bottom)? | SpellDescription$ Choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library. K:Evoke:ExileFromHand<1/Card.Blue+Other/blue card> Oracle:Flash\nFlying\nWhen Subtlety enters the battlefield, choose up to one target creature spell or planeswalker spell. Its owner puts it on the top or bottom of their library.\nEvoke—Exile a blue card from your hand. diff --git a/forge-gui/res/cardsfolder/s/subversive_acolyte.txt b/forge-gui/res/cardsfolder/s/subversive_acolyte.txt index 6cd08d591e2..0073940c32a 100644 --- a/forge-gui/res/cardsfolder/s/subversive_acolyte.txt +++ b/forge-gui/res/cardsfolder/s/subversive_acolyte.txt @@ -3,9 +3,9 @@ ManaCost:1 B Types:Creature Human PT:2/3 A:AB$ Charm | Cost$ 2 PayLife<2> | Choices$ Cleric,Phyrexian | GameActivationLimit$ 1 -SVar:Cleric:DB$ Animate | Defined$ Self | Types$ Cleric | Duration$ Permanent | SubAbility$ DBPumpCleric | StackDescription$ SpellDescription | SpellDescription$ CARDNAME becomes a Human Cleric. It gets +1/+1 and gains lifelink. +SVar:Cleric:DB$ Animate | Defined$ Self | Types$ Human Cleric | Duration$ Permanent | RemoveCreatureTypes$ True | SubAbility$ DBPumpCleric | StackDescription$ SpellDescription | SpellDescription$ CARDNAME becomes a Human Cleric. It gets +1/+1 and gains lifelink. SVar:DBPumpCleric:DB$ Pump | Defined$ Self | NumAtt$ +1 | NumDef$ +1 | KW$ Lifelink | Duration$ Permanent | StackDescription$ None -SVar:Phyrexian:DB$ Animate | Defined$ Self | Types$ Phyrexian | Triggers$ DamageSac | RemoveTypes$ Human | Duration$ Permanent | SubAbility$ DBPumpPhyrexian | SpellDescription$ CARDNAME becomes a Phyrexian. It gets +3/+2 and gains trample and "Whenever this creature is dealt damage, sacrifice that many permanents." +SVar:Phyrexian:DB$ Animate | Defined$ Self | Types$ Phyrexian | Triggers$ DamageSac | RemoveCreatureTypes$ True | Duration$ Permanent | SubAbility$ DBPumpPhyrexian | SpellDescription$ CARDNAME becomes a Phyrexian. It gets +3/+2 and gains trample and "Whenever this creature is dealt damage, sacrifice that many permanents." SVar:DBPumpPhyrexian:DB$ Pump | Defined$ Self | NumAtt$ +3 | NumDef$ +2 | KW$ Trample | Duration$ Permanent | StackDescription$ None SVar:DamageSac:Mode$ DamageDoneOnce | ValidTarget$ Card.Self | Execute$ TrigSac | TriggerZones$ Battlefield | TriggerDescription$ Whenever this creature is dealt damage, sacrifice that many permanents. SVar:TrigSac:DB$ Sacrifice | Amount$ X | SacValid$ Permanent diff --git a/forge-gui/res/cardsfolder/s/sudden_disappearance.txt b/forge-gui/res/cardsfolder/s/sudden_disappearance.txt index bb651756476..8dec3fcbe24 100644 --- a/forge-gui/res/cardsfolder/s/sudden_disappearance.txt +++ b/forge-gui/res/cardsfolder/s/sudden_disappearance.txt @@ -1,8 +1,8 @@ Name:Sudden Disappearance ManaCost:5 W Types:Sorcery -A:SP$ ChangeZoneAll | Cost$ 5 W | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Permanent.nonLand | RememberChanged$ True | SubAbility$ DelTrig | IsCurse$ True | SpellDescription$ Exile all nonland permanents target player controls. Return the exiled cards to the battlefield under their owners control at the beginning of the next end step. -SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | RememberObjects$ RememberedLKI | TriggerDescription$ Return exiled permanents to the battlefield. | SubAbility$ DBCleanup +A:SP$ ChangeZoneAll | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Permanent.nonLand | RememberChanged$ True | SubAbility$ DelTrig | IsCurse$ True | SpellDescription$ Exile all nonland permanents target player controls. Return the exiled cards to the battlefield under their owner's control at the beginning of the next end step. +SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigReturn | RememberObjects$ RememberedLKI | TriggerDescription$ Return the exiled cards to the battlefield under their owner's control at the beginning of the next end step. | SubAbility$ DBCleanup SVar:TrigReturn:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True AI:RemoveDeck:All diff --git a/forge-gui/res/cardsfolder/t/teferis_protection.txt b/forge-gui/res/cardsfolder/t/teferis_protection.txt index 26b566c2490..fdcfbbdf169 100644 --- a/forge-gui/res/cardsfolder/t/teferis_protection.txt +++ b/forge-gui/res/cardsfolder/t/teferis_protection.txt @@ -1,7 +1,9 @@ Name:Teferi's Protection ManaCost:2 W Types:Instant -A:SP$ Pump | Cost$ 2 W | Duration$ UntilYourNextTurn | Defined$ You | KW$ Your life total can't change. & Protection from everything | SubAbility$ DBPhases | SpellDescription$ Until your next turn, your life total can't change and you gain protection from everything. All permanents you control phase out. (While they're phased out, they're treated as though they don't exist. They phase in before you untap during your untap step.) Exile Teferi's Protection. +A:SP$ Effect | Name$ Teferi's Protection Effect | StaticAbilities$ STCantChange | SubAbility$ DBPump | SpellDescription$ Until your next turn, your life total can't change and you gain protection from everything. All permanents you control phase out. (While they're phased out, they're treated as though they don't exist. They phase in before you untap during your untap step.) Exile CARDNAME. +SVar:DBPump:DB$ Pump | Defined$ You | KW$ Protection from everything | SubAbility$ DBPhases +SVar:STCantChange:Mode$ CantChangeLife | ValidPlayer$ You | Description$ Your life total can't change. SVar:DBPhases:DB$ Phases | Defined$ Valid Permanent.YouCtrl | SubAbility$ DBChange SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile Oracle:Until your next turn, your life total can't change and you gain protection from everything. All permanents you control phase out. (While they're phased out, they're treated as though they don't exist. They phase in before you untap during your untap step.)\nExile Teferi's Protection. diff --git a/forge-gui/res/cardsfolder/t/the_first_iroan_games.txt b/forge-gui/res/cardsfolder/t/the_first_iroan_games.txt index 8c96fa03d46..e4f62b94369 100755 --- a/forge-gui/res/cardsfolder/t/the_first_iroan_games.txt +++ b/forge-gui/res/cardsfolder/t/the_first_iroan_games.txt @@ -5,6 +5,6 @@ K:Saga:4:TrigToken,TrigPutCounter,TrigDraw,TrigGold SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_human_soldier | TokenOwner$ You | LegacyImage$ w 1 1 human soldier thb | SpellDescription$ Create a 1/1 white Human Soldier token. SVar:TrigPutCounter:DB$ PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | CounterType$ P1P1 | CounterNum$ 3 | SpellDescription$ Put three +1/+1 counters on target creature you control. SVar:TrigDraw:DB$ Draw | NumCards$ 2 | ConditionPresent$ Creature.YouCtrl+powerGE4 | SpellDescription$ If you control a creature with power 4 or greater, draw two cards. -SVar:TrigGold:DB$ Token | TokenAmount$ 1 | TokenScript$ gold | TokenOwner$ You | LegacyImage$ gold thb | SpellDescription$ Create a Gold token. +SVar:TrigGold:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_gold_draw | TokenOwner$ You | SpellDescription$ Create a Gold token. DeckHas:Ability$Counters & Ability$Token Oracle:(As this Saga enters and after your draw step, add a lore counter. Sacrifice after IV.)\nI — Create a 1/1 white Human Soldier creature token.\nII — Put three +1/+1 counters on target creature you control.\nIII — If you control a creature with power 4 or greater, draw two cards.\nIV — Create a Gold token. (It's an artifact with "Sacrifice this artifact: Add one mana of any color.") diff --git a/forge-gui/res/cardsfolder/t/the_great_henge.txt b/forge-gui/res/cardsfolder/t/the_great_henge.txt index d2900681ce2..f7c9948cefc 100644 --- a/forge-gui/res/cardsfolder/t/the_great_henge.txt +++ b/forge-gui/res/cardsfolder/t/the_great_henge.txt @@ -3,7 +3,7 @@ ManaCost:7 G G Types:Legendary Artifact S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ CARDNAME costs {X} less to cast, where X is the greatest power among creatures you control. SVar:X:Count$GreatestPower_Creature.YouCtrl -A:AB$ Mana | Cost$ T | Produced$ G | Amount$ 2 | SubAbility$ DBGainLife | SpellDescription$ Add {G}{G}. You gain 2 life. +A:AB$ Mana | Cost$ T | Produced$ G | Amount$ 2 | SubAbility$ DBGainLife | AILogic$ AtOppEOT | SpellDescription$ Add {G}{G}. You gain 2 life. SVar:DBGainLife:DB$ GainLife | LifeAmount$ 2 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonToken+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever a nontoken creature enters the battlefield under your control, put a +1/+1 counter on it and draw a card. SVar:TrigPutCounter:DB$ PutCounter | Defined$ TriggeredCardLKICopy | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBDraw diff --git a/forge-gui/res/cardsfolder/t/the_immortal_sun.txt b/forge-gui/res/cardsfolder/t/the_immortal_sun.txt index 4d9ff83c06e..2ad9708690b 100644 --- a/forge-gui/res/cardsfolder/t/the_immortal_sun.txt +++ b/forge-gui/res/cardsfolder/t/the_immortal_sun.txt @@ -1,7 +1,7 @@ Name:The Immortal Sun ManaCost:6 Types:Legendary Artifact -S:Mode$ CantBeActivated | Activator$ Player | ValidCard$ Planeswalker | Loyalty$ True | Description$ Players can't activate planeswalkers' loyalty abilities. +S:Mode$ CantBeActivated | Activator$ Player | ValidCard$ Planeswalker | ValidSA$ Activated.Loyalty | Description$ Players can't activate planeswalkers' loyalty abilities. T:Mode$ Phase | Phase$ Draw | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ At the beginning of your draw step, draw an additional card. SVar:TrigDraw:DB$ Draw | NumCards$ 1 S:Mode$ ReduceCost | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Spells you cast cost {1} less to cast. diff --git a/forge-gui/res/cardsfolder/t/tibalt_rakish_instigator.txt b/forge-gui/res/cardsfolder/t/tibalt_rakish_instigator.txt index 8aec15d1662..b684a8d4d02 100644 --- a/forge-gui/res/cardsfolder/t/tibalt_rakish_instigator.txt +++ b/forge-gui/res/cardsfolder/t/tibalt_rakish_instigator.txt @@ -2,7 +2,7 @@ Name:Tibalt, Rakish Instigator ManaCost:2 R Types:Legendary Planeswalker Tibalt Loyalty:5 -S:Mode$ Continuous | Affected$ Player.Opponent | AddKeyword$ You can't gain life. | Description$ Your opponents can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Opponent | Description$ Your opponents can't gain life. A:AB$ Token | Cost$ SubCounter<2/LOYALTY> | TokenAmount$ 1 | TokenScript$ r_1_1_devil_burn | TokenOwner$ You | LegacyImage$ r 1 1 devil burn war | Planeswalker$ True | SpellDescription$ Create a 1/1 red Devil creature token "When this creature dies, it deals 1 damage to any target." DeckHas:Ability$Token Oracle:Your opponents can't gain life.\n[−2]: Create a 1/1 red Devil creature token with "When this creature dies, it deals 1 damage to any target." diff --git a/forge-gui/res/cardsfolder/t/treasure_trove.txt b/forge-gui/res/cardsfolder/t/treasure_trove.txt index 38afce2b22f..0f4817de58d 100644 --- a/forge-gui/res/cardsfolder/t/treasure_trove.txt +++ b/forge-gui/res/cardsfolder/t/treasure_trove.txt @@ -1,7 +1,7 @@ Name:Treasure Trove ManaCost:2 U U Types:Enchantment -A:AB$ Draw | Cost$ 2 U U | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. +A:AB$ Draw | Cost$ 2 U U | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card. SVar:NonStackingEffect:True SVar:Picture:http://www.wizards.com/global/images/magic/general/treasure_trove.jpg Oracle:{2}{U}{U}: Draw a card. diff --git a/forge-gui/res/cardsfolder/u/upwelling.txt b/forge-gui/res/cardsfolder/u/upwelling.txt index 2ef975ae615..4e152f6a070 100644 --- a/forge-gui/res/cardsfolder/u/upwelling.txt +++ b/forge-gui/res/cardsfolder/u/upwelling.txt @@ -1,8 +1,7 @@ Name:Upwelling ManaCost:3 G Types:Enchantment -S:Mode$ Continuous | GlobalRule$ Mana pools don't empty as steps and phases end. | Description$ Players don't lose unspent mana as steps and phases end. +S:Mode$ UnspentMana | Description$ Players don't lose unspent mana as steps and phases end. SVar:NonStackingEffect:True AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/upwelling.jpg Oracle:Players don't lose unspent mana as steps and phases end. diff --git a/forge-gui/res/cardsfolder/v/velis_vel.txt b/forge-gui/res/cardsfolder/v/velis_vel.txt index 5d460104fe7..0f6b549f3e8 100644 --- a/forge-gui/res/cardsfolder/v/velis_vel.txt +++ b/forge-gui/res/cardsfolder/v/velis_vel.txt @@ -4,7 +4,6 @@ Types:Plane Lorwyn S:Mode$ Continuous | Affected$ Creature | AddPower$ AffectedX | AddToughness$ AffectedX | EffectZone$ Command | Description$ Each creature gets +1/+1 for each other creature on the battlefield that shares at least one creature type with it. (For example, if two Elemental Shamans and an Elemental Spirit are on the battlefield, each gets +2/+2.) SVar:AffectedX:Count$Valid Creature.sharesCreatureTypeWith+Other T:Mode$ PlanarDice | Result$ Chaos | TriggerZones$ Command | Execute$ RolledChaos | TriggerDescription$ Whenever you roll {CHAOS}, target creature gains all creature types until end of turn. -SVar:RolledChaos:DB$ Animate | ValidTgts$ Creature | TgtPrompt$ Select target creature | Types$ AllCreatureTypes -SVar:Picture:http://www.wizards.com/global/images/magic/general/velis_vel.jpg +SVar:RolledChaos:DB$ Animate | ValidTgts$ Creature | TgtPrompt$ Select target creature | AddAllCreatureTypes$ True SVar:AIRollPlanarDieParams:Mode$ Always | HasCreatureInPlay$ True Oracle:Each creature gets +1/+1 for each other creature on the battlefield that shares at least one creature type with it. (For example, if two Elemental Shamans and an Elemental Spirit are on the battlefield, each gets +2/+2.)\nWhenever you roll {CHAOS}, target creature gains all creature types until end of turn. diff --git a/forge-gui/res/cardsfolder/v/viviens_arkbow.txt b/forge-gui/res/cardsfolder/v/viviens_arkbow.txt index 79860e04052..6f9990236c1 100644 --- a/forge-gui/res/cardsfolder/v/viviens_arkbow.txt +++ b/forge-gui/res/cardsfolder/v/viviens_arkbow.txt @@ -1,6 +1,6 @@ Name:Vivien's Arkbow ManaCost:1 G Types:Legendary Artifact -A:AB$ Dig | Cost$ X T Discard<1/Card> | DigNum$ X | AILogic$ AtOppEndOfTurn | Optional$ True | Reveal$ False | ChangeNum$ 1 | ChangeValid$ Creature.cmcLEX | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition$ -1 | RestRandomOrder$ True | SpellDescription$ Look at the top X cards of your library. You may put a creature card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. +A:AB$ Dig | Cost$ X T Discard<1/Card> | DigNum$ X | AILogic$ AtOppEOT | Optional$ True | Reveal$ False | ChangeNum$ 1 | ChangeValid$ Creature.cmcLEX | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition$ -1 | RestRandomOrder$ True | SpellDescription$ Look at the top X cards of your library. You may put a creature card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. SVar:X:Count$xPaid Oracle:{X}, {T}, Discard a card: Look at the top X cards of your library. You may put a creature card with mana value X or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/v/void.txt b/forge-gui/res/cardsfolder/v/void.txt index 620eb8340ad..3c647a1ea7e 100644 --- a/forge-gui/res/cardsfolder/v/void.txt +++ b/forge-gui/res/cardsfolder/v/void.txt @@ -4,7 +4,7 @@ Types:Sorcery A:SP$ ChooseNumber | Cost$ 3 B R | SubAbility$ DBVoidDestroyAll | SpellDescription$ Choose a number. Destroy all artifacts and creatures with mana value equal to that number. Then target player reveals their hand and discards all nonland cards with mana value equal to the number. SVar:DBVoidDestroyAll:DB$ DestroyAll | ValidCards$ Artifact.cmcEQX,Creature.cmcEQX | SubAbility$ DBVoidRevealDiscard SVar:DBVoidRevealDiscard:DB$ Discard | ValidTgts$ Player | TgtPrompt$ Select target player | Mode$ RevealDiscardAll | DiscardValid$ Card.nonLand+cmcEQX -SVar:X:Number$ChosenNumber +SVar:X:Count$ChosenNumber AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/void.jpg Oracle:Choose a number. Destroy all artifacts and creatures with mana value equal to that number. Then target player reveals their hand and discards all nonland cards with mana value equal to the number. diff --git a/forge-gui/res/cardsfolder/v/volatile_claws.txt b/forge-gui/res/cardsfolder/v/volatile_claws.txt index d55c007c59f..93dc5c55712 100644 --- a/forge-gui/res/cardsfolder/v/volatile_claws.txt +++ b/forge-gui/res/cardsfolder/v/volatile_claws.txt @@ -2,5 +2,5 @@ Name:Volatile Claws ManaCost:2 R Types:Instant A:SP$ PumpAll | Cost$ 2 R | ValidCards$ Creature.YouCtrl | NumAtt$ +2 | SubAbility$ DBAnimate | SpellDescription$ Until end of turn, creatures you control get +2/+0 and gain all creature types. -SVar:DBAnimate:DB$ AnimateAll | ValidCards$ Creature.YouCtrl | Types$ AllCreatureTypes +SVar:DBAnimate:DB$ AnimateAll | ValidCards$ Creature.YouCtrl | AddAllCreatureTypes$ True Oracle:Until end of turn, creatures you control get +2/+0 and gain all creature types. diff --git a/forge-gui/res/cardsfolder/w/whispers_of_the_muse.txt b/forge-gui/res/cardsfolder/w/whispers_of_the_muse.txt index 3e86631e731..a104412c1bc 100644 --- a/forge-gui/res/cardsfolder/w/whispers_of_the_muse.txt +++ b/forge-gui/res/cardsfolder/w/whispers_of_the_muse.txt @@ -1,7 +1,7 @@ Name:Whispers of the Muse ManaCost:U Types:Instant -A:SP$ Draw | Cost$ U | NumCards$ 1 | AILogic$ AlwaysAtOppEOT | SpellDescription$ Draw a card. +A:SP$ Draw | Cost$ U | NumCards$ 1 | AILogic$ AtOppEOT | SpellDescription$ Draw a card. K:Buyback:5 SVar:Picture:http://www.wizards.com/global/images/magic/general/whispers_of_the_muse.jpg Oracle:Buyback {5} (You may pay an additional {5} as you cast this spell. If you do, put this card into your hand as it resolves.)\nDraw a card. diff --git a/forge-gui/res/cardsfolder/w/wings_of_velis_vel.txt b/forge-gui/res/cardsfolder/w/wings_of_velis_vel.txt index db3aff63fb4..2e1bb083e93 100644 --- a/forge-gui/res/cardsfolder/w/wings_of_velis_vel.txt +++ b/forge-gui/res/cardsfolder/w/wings_of_velis_vel.txt @@ -2,7 +2,6 @@ Name:Wings of Velis Vel ManaCost:1 U Types:Tribal Instant Shapeshifter K:Changeling -A:SP$ Animate | Cost$ 1 U | ValidTgts$ Creature | TgtPrompt$ Select target creature | Power$ 4 | Toughness$ 4 | Keywords$ Flying | Types$ AllCreatureTypes | SpellDescription$ Until end of turn, target creature has base power and toughness 4/4, gains all creature types, and gains flying. +A:SP$ Animate | Cost$ 1 U | ValidTgts$ Creature | TgtPrompt$ Select target creature | Power$ 4 | Toughness$ 4 | Keywords$ Flying | AddAllCreatureTypes$ True | SpellDescription$ Until end of turn, target creature has base power and toughness 4/4, gains all creature types, and gains flying. AI:RemoveDeck:All -SVar:Picture:http://www.wizards.com/global/images/magic/general/wings_of_velis_vel.jpg Oracle:Changeling (This card is every creature type.)\nUntil end of turn, target creature has base power and toughness 4/4, gains all creature types, and gains flying. diff --git a/forge-gui/res/cardsfolder/w/witch_hunt.txt b/forge-gui/res/cardsfolder/w/witch_hunt.txt index 7475a1a132a..06cae0ca0c6 100644 --- a/forge-gui/res/cardsfolder/w/witch_hunt.txt +++ b/forge-gui/res/cardsfolder/w/witch_hunt.txt @@ -1,10 +1,9 @@ Name:Witch Hunt ManaCost:4 R Types:Enchantment -S:Mode$ Continuous | Affected$ Player | AddKeyword$ You can't gain life. | Description$ Players can't gain life. +S:Mode$ CantGainLife | ValidPlayer$ Player | Description$ Players can't gain life. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDmg | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 4 damage to you. SVar:TrigDmg:DB$ DealDamage | Defined$ You | NumDmg$ 4 T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigGainControl | TriggerDescription$ At the beginning of your end step, target opponent chosen at random gains control of CARDNAME. SVar:TrigGainControl:DB$ GainControl | ValidTgts$ Opponent | TargetsAtRandom$ True | Defined$ Self -SVar:Picture:http://www.wizards.com/global/images/magic/general/witch_hunt.jpg Oracle:Players can't gain life.\nAt the beginning of your upkeep, Witch Hunt deals 4 damage to you.\nAt the beginning of your end step, target opponent chosen at random gains control of Witch Hunt. diff --git a/forge-gui/res/cardsfolder/y/yusri_fortunes_flame.txt b/forge-gui/res/cardsfolder/y/yusri_fortunes_flame.txt index 14d7bc542a7..65f887fd54c 100644 --- a/forge-gui/res/cardsfolder/y/yusri_fortunes_flame.txt +++ b/forge-gui/res/cardsfolder/y/yusri_fortunes_flame.txt @@ -11,7 +11,7 @@ SVar:DBDamage:DB$ DealDamage | NumDmg$ Damage | Defined$ You SVar:DBEffect:DB$ Effect | StaticAbilities$ MayPlay | Stackable$ False | ConditionCheckSVar$ Y | ConditionSVarCompare$ EQ5 | SubAbility$ DBCleanup SVar:MayPlay:Mode$ Continuous | EffectZone$ Command | Affected$ Card.nonLand+YouOwn | MayPlay$ True | MayPlayWithoutManaCost$ True | AffectedZone$ Hand | Description$ You may cast spells from your hand this turn without paying their mana costs. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:X:Number$ChosenNumber +SVar:X:Count$ChosenNumber SVar:Y:Count$RememberedNumber SVar:Damage:SVar$Losses/Times.2 Oracle:Flying\nWhenever Yusri, Fortune's Flame attacks, choose a number between 1 and 5. Flip that many coins. For each flip you win, draw a card. For each flip you lose, Yusri deals 2 damage to you. If you won five flips this way, you may cast spells from your hand this turn without paying their mana costs. diff --git a/forge-gui/res/deckgendecks/Historic.lda.dat b/forge-gui/res/deckgendecks/Historic.lda.dat index 27338a3c2c0..77e0033eb89 100644 Binary files a/forge-gui/res/deckgendecks/Historic.lda.dat and b/forge-gui/res/deckgendecks/Historic.lda.dat differ diff --git a/forge-gui/res/deckgendecks/Historic.raw.dat b/forge-gui/res/deckgendecks/Historic.raw.dat index 282c454684d..5dcbb406d3a 100644 Binary files a/forge-gui/res/deckgendecks/Historic.raw.dat and b/forge-gui/res/deckgendecks/Historic.raw.dat differ diff --git a/forge-gui/res/deckgendecks/Modern.lda.dat b/forge-gui/res/deckgendecks/Modern.lda.dat index 7856563031e..07efba0ed04 100644 Binary files a/forge-gui/res/deckgendecks/Modern.lda.dat and b/forge-gui/res/deckgendecks/Modern.lda.dat differ diff --git a/forge-gui/res/deckgendecks/Modern.raw.dat b/forge-gui/res/deckgendecks/Modern.raw.dat index 4cd7732ee12..2e5879a1b80 100644 Binary files a/forge-gui/res/deckgendecks/Modern.raw.dat and b/forge-gui/res/deckgendecks/Modern.raw.dat differ diff --git a/forge-gui/res/deckgendecks/Standard.lda.dat b/forge-gui/res/deckgendecks/Standard.lda.dat index 1454252f4bf..64cbf4a4e4d 100644 Binary files a/forge-gui/res/deckgendecks/Standard.lda.dat and b/forge-gui/res/deckgendecks/Standard.lda.dat differ diff --git a/forge-gui/res/deckgendecks/Standard.raw.dat b/forge-gui/res/deckgendecks/Standard.raw.dat index 049bb6290f7..70bb648eeea 100644 Binary files a/forge-gui/res/deckgendecks/Standard.raw.dat and b/forge-gui/res/deckgendecks/Standard.raw.dat differ diff --git a/forge-gui/res/editions/Born of the Gods.txt b/forge-gui/res/editions/Born of the Gods.txt index 45744bbeadf..dca7cff47c0 100644 --- a/forge-gui/res/editions/Born of the Gods.txt +++ b/forge-gui/res/editions/Born of the Gods.txt @@ -178,14 +178,14 @@ ScryfallCode=BNG 165 R Temple of Plenty @Noah Bradley [tokens] -gold +b_2_2_e_zombie +c_a_gold_draw +g_2_2_wolf +g_3_3_e_centaur +r_3_1_e_elemental_haste +u_2_2_e_bird_flying +u_9_9_kraken w_1_1_bird_flying w_1_1_cat_soldier_vigilance w_1_1_e_soldier w_1_1_e_soldier -u_2_2_e_bird_flying -u_9_9_kraken -b_2_2_e_zombie -r_3_1_e_elemental_haste -g_3_3_e_centaur -g_2_2_wolf diff --git a/forge-gui/res/editions/Commander 2015.txt b/forge-gui/res/editions/Commander 2015.txt index b2bf7cf5024..02e4b4e7415 100644 --- a/forge-gui/res/editions/Commander 2015.txt +++ b/forge-gui/res/editions/Commander 2015.txt @@ -352,27 +352,27 @@ ScryfallCode=C15 342 L Forest @Jonas De Ro [tokens] -gold -lightning_rager -c_1_1_shapeshifter_changeling -w_4_4_angel_flying -w_2_2_cat -w_2_2_knight_first_strike -w_2_2_knight_vigilance -u_2_2_drake_flying b_0_0_phyrexian_germ b_2_2_zombie -r_5_5_dragon_flying -r_3_1_elemental_shaman_haste -g_2_2_bear -g_4_4_phyrexian_beast -g_3_3_elephant -g_3_3_frog_lizard +c_1_1_shapeshifter_changeling +c_a_gold_draw g_1_1_saproling g_1_1_snake g_1_2_spider_reach +g_2_2_bear g_2_2_wolf -ur_5_5_elemental_flying +g_3_3_elephant +g_3_3_frog_lizard +g_4_4_phyrexian_beast gu_1_1_snake -wb_x_x_e_spirit_experience +lightning_rager +r_3_1_elemental_shaman_haste +r_5_5_dragon_flying +u_2_2_drake_flying +ur_5_5_elemental_flying +w_2_2_cat +w_2_2_knight_first_strike +w_2_2_knight_vigilance +w_4_4_angel_flying wb_1_1_spirit_flying +wb_x_x_e_spirit_experience diff --git a/forge-gui/res/editions/Commander 2017.txt b/forge-gui/res/editions/Commander 2017.txt index d9175a731fe..0179c675af5 100644 --- a/forge-gui/res/editions/Commander 2017.txt +++ b/forge-gui/res/editions/Commander 2017.txt @@ -319,14 +319,14 @@ ScryfallCode=C17 309 L Forest @Kev Walker [tokens] -gold -c_0_1_eldrazi_spawn_sac -w_2_2_cat b_1_1_bat_flying b_1_1_rat_deathtouch b_1_1_vampire b_2_2_zombie +brg_3_3_cat_dragon_flying +c_0_1_eldrazi_spawn_sac +c_a_gold_draw +g_2_2_cat_warrior_forestwalk r_4_4_dragon_flying r_6_6_dragon_flying -g_2_2_cat_warrior_forestwalk -brg_3_3_cat_dragon_flying +w_2_2_cat diff --git a/forge-gui/res/editions/Happy Holidays.txt b/forge-gui/res/editions/Happy Holidays.txt index c147fa6ae50..5bb7a2fd0ea 100644 --- a/forge-gui/res/editions/Happy Holidays.txt +++ b/forge-gui/res/editions/Happy Holidays.txt @@ -8,4 +8,18 @@ ScryfallCode=HHO [cards] 6 R Fruitcake Elemental @Darrell Riche +7 R Gifts Given @Jason Chan +8 R Evil Presents @Paul Bonner 9 R Season's Beatings @Kev Walker +10 R Snow Mercy @rk post +11 R Yule Ooze @Steve Prescott +12 R Naughty // Nice @Greg Staples +13 R Stocking Tiger @Terese Nielsen +14 M Mishra's Toy Workshop @Jung Park +15 M Goblin Sleigh Ride @Mark Zug +16 M Thopter Pie Network @Victor Adame Minguez +17 M Some Disassembly Required @Dmitry Burmak +18 M Bog Humbugs @Kieran Yanner +19 M Decorated Knight @Zoltan Boros +20 M Topdeck the Halls @Kieran Yanner +21 M Last-Minute Chopping @Marta Nael diff --git a/forge-gui/res/editions/Journey into Nyx.txt b/forge-gui/res/editions/Journey into Nyx.txt index 55f83525143..8003caeadc6 100644 --- a/forge-gui/res/editions/Journey into Nyx.txt +++ b/forge-gui/res/editions/Journey into Nyx.txt @@ -178,16 +178,16 @@ ScryfallCode=JOU 165 R Temple of Malady @James Paick [tokens] -gold -w_1_1_soldier -w_1_1_soldier -w_1_1_soldier +b_x_x_zombie +bg_1_1_e_snake_deathtouch +c_a_gold_draw +g_1_3_e_spider_reach +g_x_x_hydra +r_2_3_minotaur_haste +r_2_3_minotaur_haste +rg_2_2_satyr_haste u_2_2_e_bird_flying u_4_4_sphinx_flying -b_x_x_zombie -r_2_3_minotaur_haste -r_2_3_minotaur_haste -g_x_x_hydra -g_1_3_e_spider_reach -rg_2_2_satyr_haste -bg_1_1_e_snake_deathtouch +w_1_1_soldier +w_1_1_soldier +w_1_1_soldier diff --git a/forge-gui/res/editions/Kaldheim.txt b/forge-gui/res/editions/Kaldheim.txt index 34ac30035e0..a0b476744c0 100644 --- a/forge-gui/res/editions/Kaldheim.txt +++ b/forge-gui/res/editions/Kaldheim.txt @@ -454,22 +454,22 @@ ScryfallCode=KHM 2 Woodland Chasm|KHM [tokens] -w_4_4_angel_warrior_flying_vigilance -w_1_1_human_warrior -w_1_1_spirit_flying -u_1_1_bird_flying -u_4_4_giant_wizard -komas_coil -u_2_2_shapeshifter_changeling b_2_2_zombie_berserker -r_2_3_demon_berserker_menace -r_5_5_dragon_flying -r_2_1_dwarf_berserker +c_a_treasure_sac +c_e_shard_draw +g_1_1_elf_warrior g_2_2_bear g_2_2_cat -g_1_1_elf_warrior g_4_4_troll_warrior_trample -c_a_treasure_sac icy_manalith +komas_coil +r_2_1_dwarf_berserker +r_2_3_demon_berserker_menace +r_5_5_dragon_flying replicated_ring -shard +u_1_1_bird_flying +u_2_2_shapeshifter_changeling +u_4_4_giant_wizard +w_1_1_human_warrior +w_1_1_spirit_flying +w_4_4_angel_warrior_flying_vigilance diff --git a/forge-gui/res/editions/Secret Lair Drop Series.txt b/forge-gui/res/editions/Secret Lair Drop Series.txt index b8a9d120cca..49b189e40a7 100644 --- a/forge-gui/res/editions/Secret Lair Drop Series.txt +++ b/forge-gui/res/editions/Secret Lair Drop Series.txt @@ -184,6 +184,9 @@ ScryfallCode=SLD 203 R Commander's Sphere @Yosuke Ueno 204 R Darksteel Ingot @Theodoru 205 R Gilded Lotus @Mab Graves +206 R Exquisite Blood @Nils Hamm +207 R Night's Whisper @Tomas Duchek +208 R Phyrexian Tower @Nicholas Gregory 209 M Elesh Norn, Grand Cenobite @Igor Kieryluk 210 M Jin-Gitaxias, Core Augur @Eric Deschamps 211 M Sheoldred, Whispering One @Jana Schirmer & Johannes Voss @@ -200,6 +203,11 @@ ScryfallCode=SLD 223 M Grave Titan @GodMachine 224 M Inferno Titan @Dibujante Nocturno 225 M Kroxa, Titan of Death's Hunger @DZO +226 R Path to Exile @Marija Tiurina +227 R Well of Lost Dreams @Marija Tiurina +228 R Frantic Search @Marija Tiurina +229 R Intruder Alarm @Marija Tiurina +230 R Shelldock Isle @Marija Tiurina 231 R Gravecrawler @Fay Dalton 232 M Liliana, Death's Majesty @Fay Dalton 233 M Rise of the Dark Realms @Fay Dalton @@ -270,6 +278,11 @@ ScryfallCode=SLD 302 R Vault of Whispers @DXTR 303 R Great Furnace @DXTR 304 R Tree of Tales @DXTR +305 R Ravenous Chupacabra @Crocodile Jackson +306 R Managorger Hydra @Crocodile Jackson +307 R Pathbreaker Ibex @Crocodile Jackson +308 R Temur Sabertooth @Crocodile Jackson +309 R Winding Constrictor @Crocodile Jackson 310 R Unbreakable Formation @Tyler Walpole 311 R Whir of Invention @Tyler Walpole 312 R Hero's Downfall @Tyler Walpole @@ -285,6 +298,16 @@ ScryfallCode=SLD 322 R Blasphemous Act @Martin Ansin 323 R Beast Within @Martin Ansin 324 R Grafdigger's Cage @Martin Ansin +325 R Snow-Covered Plains @Jubilee +326 R Snow-Covered Island @Jubilee +327 R Snow-Covered Swamp @Jubilee +328 R Snow-Covered Mountain @Jubilee +329 R Snow-Covered Forest @Jubilee +330 R Aether Gust @Mateus Manhanini +331 R Counterspell @Mateus Manhanini +332 R Fabricate @Mateus Manhanini +333 R Fact or Fiction @Mateus Manhanini +334 R Mystical Tutor @Mateus Manhanini 340 M Mind Flayer, the Shadow @Isis 341 R Chief Jim Hopper @Greg Staples 342 R Dustin, Gadget Genius @Colin Boyer @@ -303,6 +326,11 @@ ScryfallCode=SLD 356 R Slayers' Stronghold @Alayna Danner 357 R Gavony Township @Robbie Trevino 358 R Alchemist's Refuge @DZO +359 R Plains @Donato Giancola +360 R Island @Yeong-Hao Han +361 R Swamp @Jonas De Ro +362 R Mountain @Grzegorz Rutkowski +363 R Forest @Andreas Rocha 364 R Swords to Plowshares @MSCHF 365 R Grim Tutor @MSCHF 366 R Blood Moon @MSCHF @@ -318,15 +346,28 @@ ScryfallCode=SLD 376 M Craterhoof Behemoth @Kira 377 R Metalwork Colossus @Chris Rahn 378 R Metalwork Colossus @Hyan Tran +379 R Zndrsplt, Eye of Wisdom @Alexis Ziritt +379b R Zndrsplt, Eye of Wisdom @Alexis Ziritt +380 R Okaun, Eye of Chaos @Alexis Ziritt +380b R Okaun, Eye of Chaos @Alexis Ziritt +381 R Propaganda @Scott Balmer +381b R Propaganda @Scott Balmer +382 R Stitch in Time @Micha Huigen +382b R Stitch in Time @Micha Huigen +383 R Krark's Thumb @Wooden Cyclops +383b R Krark's Thumb @Wooden Cyclops 477 R Path to Exile @Riot Games 478 R Rhystic Study @Riot Games +479 R Duress @Riot Games +480 R Seize the Day @Riot Games +481 R Krosan Grip @Riot Games 482 R Counterflux @Riot Games 483 R Thran Dynamo @Riot Games -484 L Plains @Riot Games -485 L Island @Riot Games -486 L Swamp @Riot Games -487 L Mountain @Riot Games -488 L Forest @Riot Games +484 R Plains @Riot Games +485 R Island @Riot Games +486 R Swamp @Riot Games +487 R Mountain @Riot Games +488 R Forest @Riot Games 501 R Karn, the Great Creator @Wisnu Tan 502 R Ugin, the Ineffable @Daarken 503 M Gideon Blackblade @Kieran Yanner diff --git a/forge-gui/res/editions/The List.txt b/forge-gui/res/editions/The List.txt index b1c1d9fd687..9370328890b 100644 --- a/forge-gui/res/editions/The List.txt +++ b/forge-gui/res/editions/The List.txt @@ -583,3 +583,78 @@ F567 R Puresteel Angel @Lukas Litzsinger 575 U Karoo @Zina Saunders 576 U Orzhova, the Church of Deals @Martina Pilcerova 577 R Unholy Grotto @John Avon +578 C Benediction of Moons @Matt Cavotta +579 C Late to Dinner @Kev Walker +580 U Light of Day @Drew Tucker +581 R Odric, Master Tactician @Michael Komarck +582 C Sacred Rites @Bradley Williams +583 R Sanguine Sacrament @Bastien L. Deharme +584 R Second Sunrise @Greg Staples +585 U Skymarcher Aspirant @Winona Nelson +586 U Starnheim Aspirant @Kieran Yanner +587 R Thalia's Lieutenant @Johannes Voss +588 S Baral, Chief of Compliance @Wesley Burt +589 U Brinelin, the Moon Kraken @Adam Paquette +590 M Day's Undoing @Jonas De Ro +591 C Floodhound @Lius Lasahido +592 R Profaner of the Dead @Vincent Proce +593 U Silumgar Sorcerer @Jeff Simpson +594 R Bad Moon @Gary Leach +595 R Bloodchief Ascension @Adi Granov +596 C Blood Pet @Brom +597 M Cavalier of Night @Viktor Titov +598 R Exquisite Blood @Cynthia Sheppard +599 R Geralf's Messenger @Kev Walker +600 R Guul Draz Assassin @James Ryman +601 R Sign in Blood @Alan Pollack +602 M Sorin Markov @Michael Komarck +603 R Sorin's Vengeance @Jana Schirmer +604 M Twilight Prophet @Seb McKinnon +605 U Vampiric Feast @D. Alexander Gregory +606 M Vampiric Tutor @Raymond Swanland +607 U Wall of Blood @Tony Szczudlo +608 R Blood Moon @Franz Vohwinkel +609 U Blood Rites @Raymond Swanland +610 C Boiling Blood @Cliff Nielsen +611 C Ceremonial Guard @Daren Bader +612 M Chandra Nalaar @Aleksi Briclot +613 U Crimson Muckwader @Steven Belledin +614 U Vow of Lightning @Randy Vargas +615 U Assault Formation @Kieran Yanner +616 C Commencement of Festivities @Zack Stella +617 U Cult of the Waxing Moon @Anastasia Ovchinnikova +618 R Deathcoil Wurm @Rebecca Guay +619 U Exuberant Wolfbear @Jesper Ejsing +620 R Gutter Grime @Erica Yang +621 U Joraga Treespeaker @Cyril Van Der Haegen +622 R Mongrel Pack @Jeff Miracola +623 U Noxious Revival @Matt Stewart +624 R Pir's Whim @Jakub Kasper +625 U Song of Freyalise @Min Yum +626 U Strangleroot Geist @Erica Yang +627 R Witchstalker @Christopher Moeller +628 U Belligerent Brontodon @Dan Scott +629 U Cruel Celebrant @Bastien L. Deharme +630 M Gisa and Geralf @Karla Ortiz +631 M Karador, Ghost Chieftain @Todd Lockwood +632 M Vela the Night-Clad @Allen Williams +633 R Witch-Maw Nephilim @Greg Staples +634 U Dryad Militant @Ryan Pancoast +635 U Mistmeadow Witch @Greg Staples +636 U Moonhold @Mike Dringenberg +637 R Murkfiend Liege @Carl Critchlow +638 R Wheel of Sun and Moon @Zoltan Boros +639 R Flesh // Blood @Lucas Graciano +640 R Blood Clock @Keith Garletts +641 R Howling Mine @Ralph Horsley +642 R Jet Medallion @Sue Ellen Brown +643 R Juntu Stakes @Mark Brill +644 U Lunar Avenger @Paolo Parente +645 U Perpetual Timepiece @Cliff Childs +646 C Training Drone @Matt Cavotta +647 R Unwinding Clock @Mike Bierek +648 U Witches' Eye @Daniel Ljunggren +649 C Wooden Stake @David Palumbo +650 R Blood Crypt @Rob Alexander +651 R Shinka, the Bloodsoaked Keep @Thomas M. Baxa +652 R Shivan Gorge @John Matson diff --git a/forge-gui/res/editions/Theros Beyond Death.txt b/forge-gui/res/editions/Theros Beyond Death.txt index 8686f7d3574..f1505d83dd0 100644 --- a/forge-gui/res/editions/Theros Beyond Death.txt +++ b/forge-gui/res/editions/Theros Beyond Death.txt @@ -655,10 +655,11 @@ Unknown Shores|THB|1 [tokens] b_2_2_zombie c_0_4_a_wall_defender +c_a_gold_draw g_1_2_spider_reach g_2_2_wolf -r_x_1_elemental_trample_haste r_1_1_satyr_noblock +r_x_1_elemental_trample_haste u_1_1_tentacle u_3_2_reflection u_8_8_kraken_hexproof @@ -666,4 +667,3 @@ ub_2_3_nightmare_mill w_0_1_goat w_1_1_human_soldier w_2_2_pegasus_flying -gold diff --git a/forge-gui/res/editions/Unfinity.txt b/forge-gui/res/editions/Unfinity.txt new file mode 100644 index 00000000000..77aa15c667f --- /dev/null +++ b/forge-gui/res/editions/Unfinity.txt @@ -0,0 +1,35 @@ +[metadata] +Code=UNF +Date=2022-04-01 +Name=Unfinity +MciCode=unf +Type=Funny +ScryfallCode=UNF + +[cards] +3 U Assembled Ensemble @Jakub Kasper +88 R Saw in Half @Sebastian Giacobino +143 M Killer Cosplay @Leonardo Santanna +179 U The Space Family Goblinson @Armand Baltazar +235 L Plains @Adam Paquette +236 L Island @Adam Paquette +237 L Swamp @Adam Paquette +238 L Mountain @Adam Paquette +239 L Forest @Adam Paquette +240 L Plains @Adam Paquette +241 L Island @Adam Paquette +242 L Swamp @Adam Paquette +243 L Mountain @Adam Paquette +244 L Forest @Adam Paquette +270 U The Space Family Goblinson @David Semple +277 R Hallowed Fountain @Piotr Dura +278 R Watery Grave @Chris Ostrowski +279 R Blood Crypt @Chris Ostrowski +280 R Stomping Ground @Bruce Brenneise +281 R Temple Garden @Piotr Dura +282 R Godless Shrine @Bruce Brenneise +283 R Steam Vents @Piotr Dura +284 R Overgrown Tomb @Cliff Childs +285 R Sacred Foundry @Cliff Childs +286 R Breeding Pool @Bruce Brenneise +538 R Water Gun Balloon Game @Ralph Horsley diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 19b9c686443..55cdbcfa13b 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -286,6 +286,7 @@ lblTryAgain=Neu lblAddAPlayer=Spieler hinzufügen lblVariants=Varianten lblRandom=Zufällig +lblGamesInMatch=Spiele pro Partie: #VSubmenuConstructed.java lblConstructedMode=Constructed-Modus lblConstructed=Constructed @@ -1398,7 +1399,7 @@ lblLostDueToAccumulationOf21DamageFromGenerals=hat durch Anhäufen von 21 oder m lblAcceptedThatTheGameIsADraw=hat ein Unentschieden akzeptiert lblLostForUnknownReasonBug=hat aus unbekannten Gründen verloren (Dies ist ein Fehler!) #ViewWinLose.java -btnNextGame=Nächste Partie +btnNextGame=Nächstes Spiel btnStartNewMatch=Starte neue Partie btnQuitMatch=Beende Partie lblItsADraw=Es ist ein Unentschieden! diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 4fb81972a17..b53e2269736 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -287,6 +287,7 @@ lblTryAgain=Try Again lblAddAPlayer=Add a Player lblVariants=Variants lblRandom=Random +lblGamesInMatch=Games in match: #VSubmenuConstructed.java lblConstructedMode=Constructed Mode lblConstructed=Constructed diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index d3f55563e11..6918644bc44 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -287,6 +287,7 @@ lblTryAgain=Probar de nuevo lblAddAPlayer=Añadir jugador lblVariants=Variantes lblRandom=Aleatorio +lblGamesInMatch=Games in match: #VSubmenuConstructed.java lblConstructedMode=Modo Construido lblConstructed=Construido diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index c56d0a9a192..7e6274e353b 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -286,6 +286,7 @@ lblTryAgain=Riprova lblAddAPlayer=Aggiungi un giocatore lblVariants=Varianti lblRandom=Casuale +lblGamesInMatch=Games in match: #VSubmenuConstructed.java lblConstructedMode=Modalità costruita lblConstructed=Costruito diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index e6d13cfe422..8e178df7c92 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -287,6 +287,7 @@ lblTryAgain=再試行 lblAddAPlayer=プレーヤーを追加 lblVariants=バリエーション lblRandom=ランダム +lblGamesInMatch=Games in match: #VSubmenuConstructed.java lblConstructedMode=構築戦 lblConstructed=構築戦 diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 67603f42625..cf68ba49c37 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -112,8 +112,8 @@ cbpGameLogEntryType=游戏日志详细程度 cbpCloseAction=关闭动作 cbpDefaultFontSize=默认字体大小 cbpCardArtFormat=牌张插画格式 -cbpSoundSets=Sound Set -cbpMusicSets=Music Set +cbpSoundSets=音效集 +cbpMusicSets=音乐集 cbpAiProfiles=AI强度 cbpStackAdditions=堆叠效应通知 cbpDisplayCurrentCardColors=显示卡牌颜色详情 @@ -144,8 +144,8 @@ nlCompactMainMenu=启用节省空间的侧边栏,一次只显示一个菜单 nlUseSentry=启用后,会自动向开发人员提交错误报告。 GamePlay=游戏 nlpMulliganRule=选择调度规则 -nlpSoundSets=Choose the sound set from the ones present in the "sound" folder in your Forge cache directory -nlpMusicSets=Choose the music set from the ones present in the "music" folder in your Forge cache directory +nlpSoundSets=从Forge的缓存目录中的\"sound\"文件夹中选择音效集 +nlpMusicSets=从Forge的缓存目录中的\"music\"文件夹中选择音乐集 nlpAiProfiles=选择你的AI对手 nlpStackAdditions=选择何时因效应进入堆叠而提供视觉提醒:从不,总是,任何由AI释放或起动以及由任何玩家触发的效应。 nlAnte=确定游戏是否使用赌注 @@ -287,6 +287,7 @@ lblTryAgain=再试一次 lblAddAPlayer=增加一个玩家 lblVariants=变种 lblRandom=随机 +lblGamesInMatch=一场游戏打几小局: #VSubmenuConstructed.java lblConstructedMode=构筑模式 lblConstructed=构筑 @@ -1595,7 +1596,7 @@ lblTapped=已横置 lblTappedForMana=为法术力横置 lblProduced=产生 #TriggerTrains.java -lblTrains=Trains +lblTrains=见习中 #TriggerTransformed.java lblTransformed=已转化 #TriggerTurnFaceUp.java @@ -1993,7 +1994,7 @@ lblPlayerRolledResult={0}掷骰结果为{1} lblDoYouWantPayEcho=你想支付返响费用 lblPayEcho=支付返响费用 lblDoYouWantSacrifice=你想牺牲吗? -lblDoYouWantSacrificeThis=Do you want to sacrifice {0}? +lblDoYouWantSacrificeThis=你想要牺牲{0}吗? #SetStateEffect.java lblFaceDownCardCantTurnFaceUp=面朝下的牌不能面朝上 #ShuffleEffect.java @@ -2673,9 +2674,9 @@ lblUseFormatFilter=选择牌张列表的格式 lblIgnoreBnR=禁限卡也导入 ttIgnoreBnR=如果启用,禁限卡也将被导入。 nlIgnoreBnR=警告:如果启用了套牌一致性,套牌可能无法使用。 -lblUseSmartCardArt=Enable Smart Card Art Selection -ttUseSmartCardArtNoDeck=If enabled, the art of cards will be automatically chosen to match up with other cards in the Decklist. -ttUseSmartCardArtWithDeck=If enabled, the art of cards will be automatically chosen to match up with other cards in the Decklist, and in current Deck. +lblUseSmartCardArt=启用智能卡图选择 +ttUseSmartCardArtNoDeck=如果启用,将自动选择与套牌中其他单卡相匹配的卡图。 +ttUseSmartCardArtWithDeck=如果启用,将自动选择与套牌中其他单卡相匹配的卡图。 lblExtraOptions=显示选项 lblHideOptions=隐藏选项 lblCardPreview=牌张预览 diff --git a/forge-gui/res/lists/TypeLists.txt b/forge-gui/res/lists/TypeLists.txt index a0003cb3d5d..d004efe5b35 100644 --- a/forge-gui/res/lists/TypeLists.txt +++ b/forge-gui/res/lists/TypeLists.txt @@ -300,6 +300,7 @@ Curse Rune Saga Shrine +Shard [ArtifactTypes] Blood Clue:Clues diff --git a/forge-gui/res/lists/net-decks-archive-legacy.txt b/forge-gui/res/lists/net-decks-archive-legacy.txt index 417d7d765ab..7c9ce35ae92 100644 --- a/forge-gui/res/lists/net-decks-archive-legacy.txt +++ b/forge-gui/res/lists/net-decks-archive-legacy.txt @@ -2148,3 +2148,14 @@ 2021-11-06 Legacy Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-06-legacy-preliminary.zip 2021-11-08 Legacy Showcase Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-08-legacy-showcase-challenge.zip 2021-11-10 Legacy Preliminary (5 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-10-legacy-preliminary.zip +2021-11-12 Legacy Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-12-legacy-preliminary.zip +2021-11-13 Legacy League (17 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-13-legacy-league.zip +2021-11-15 Legacy Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-15-legacy-challenge.zip +2021-11-19 Legacy Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-19-legacy-preliminary.zip +2021-11-20 Legacy League (49 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-20-legacy-league.zip +2021-11-21 0 Legacy Premier (16 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-21-0-legacy-premier.zip +2021-11-21 Legacy Premier (16 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-21-legacy-premier.zip +2021-11-22 Legacy Premier (16 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-22-legacy-premier.zip +2021-11-23 Legacy Preliminary (5 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-23-legacy-preliminary.zip +2021-11-25 Legacy Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-25-legacy-preliminary.zip +2021-11-26 Legacy Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/legacy/2021-11-26-legacy-preliminary.zip diff --git a/forge-gui/res/lists/net-decks-archive-modern.txt b/forge-gui/res/lists/net-decks-archive-modern.txt index ae7bc4a5515..759089a1e4e 100644 --- a/forge-gui/res/lists/net-decks-archive-modern.txt +++ b/forge-gui/res/lists/net-decks-archive-modern.txt @@ -2831,3 +2831,25 @@ 2021-11-09 Modern League (69 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-09-modern-league.zip 2021-11-09 Modern Preliminary (8 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-09-modern-preliminary.zip 2021-11-10 Modern Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-10-modern-preliminary.zip +2021-11-11 Modern Preliminary (9 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-11-modern-preliminary.zip +2021-11-12 Modern League (26 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-12-modern-league.zip +2021-11-12 Modern Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-12-modern-preliminary.zip +2021-11-13 Modern Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-13-modern-preliminary.zip +2021-11-14 Modern Showcase Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-14-modern-showcase-challenge.zip +2021-11-15 Modern Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-15-modern-challenge.zip +2021-11-16 Modern League (65 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-16-modern-league.zip +2021-11-16 Modern Preliminary (7 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-16-modern-preliminary.zip +2021-11-17 Modern Preliminary (5 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-17-modern-preliminary.zip +2021-11-18 Modern Preliminary (8 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-18-modern-preliminary.zip +2021-11-19 Modern League (63 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-19-modern-league.zip +2021-11-19 Modern Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-19-modern-preliminary.zip +2021-11-20 Modern Preliminary (6 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-20-modern-preliminary.zip +2021-11-21 Modern Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-21-modern-challenge.zip +2021-11-22 Modern Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-22-modern-challenge.zip +2021-11-22 Modern Premier (16 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-22-modern-premier.zip +2021-11-23 Modern League (63 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-23-modern-league.zip +2021-11-23 Modern Preliminary (6 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-23-modern-preliminary.zip +2021-11-24 Modern Preliminary (5 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-24-modern-preliminary.zip +2021-11-25 Modern Preliminary (10 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-25-modern-preliminary.zip +2021-11-26 Modern League (66 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-26-modern-league.zip +2021-11-26 Modern Preliminary (7 decks) | https://downloads.cardforge.org/decks/archive/modern/2021-11-26-modern-preliminary.zip diff --git a/forge-gui/res/lists/net-decks-archive-pauper.txt b/forge-gui/res/lists/net-decks-archive-pauper.txt index da8d8a646a1..f0a3577a1af 100644 --- a/forge-gui/res/lists/net-decks-archive-pauper.txt +++ b/forge-gui/res/lists/net-decks-archive-pauper.txt @@ -1828,3 +1828,10 @@ 2021-11-07 Pauper Showcase Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-11-07-pauper-showcase-challenge.zip 2021-11-08 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-11-08-pauper-challenge.zip 2021-11-10 Pauper League (25 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-11-10-pauper-league.zip +2021-11-14 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-11-14-pauper-challenge.zip +2021-11-15 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-11-15-pauper-challenge.zip +2021-11-17 Pauper League (23 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-11-17-pauper-league.zip +2021-11-21 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-11-21-pauper-challenge.zip +2021-11-22 Pauper Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-11-22-pauper-challenge.zip +2021-11-24 Pauper League (26 decks) | https://downloads.cardforge.org/decks/archive/pauper/2021-11-24-pauper-league.zip +Pauper League (20 decks) | https://downloads.cardforge.org/decks/archive/pauper/pauper-league.zip diff --git a/forge-gui/res/lists/net-decks-archive-pioneer.txt b/forge-gui/res/lists/net-decks-archive-pioneer.txt index eb0e0f63033..2a085617425 100644 --- a/forge-gui/res/lists/net-decks-archive-pioneer.txt +++ b/forge-gui/res/lists/net-decks-archive-pioneer.txt @@ -773,3 +773,21 @@ 2021-11-07 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-07-pioneer-challenge.zip 2021-11-08 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-08-pioneer-challenge.zip 2021-11-08 Pioneer League (13 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-08-pioneer-league.zip +2021-11-11 Pioneer League (14 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-11-pioneer-league.zip +2021-11-12 Pioneer Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-12-pioneer-preliminary.zip +2021-11-13 Pioneer Preliminary (8 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-13-pioneer-preliminary.zip +2021-11-14 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-14-pioneer-challenge.zip +2021-11-14 Pioneer Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-14-pioneer-preliminary.zip +2021-11-15 Pioneer League (28 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-15-pioneer-league.zip +2021-11-15 Pioneer Showcase Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-15-pioneer-showcase-challenge.zip +2021-11-18 Pioneer League (17 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-18-pioneer-league.zip +2021-11-18 Pioneer Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-18-pioneer-preliminary.zip +2021-11-20 Pioneer Preliminary (6 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-20-pioneer-preliminary.zip +2021-11-21 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-21-pioneer-challenge.zip +2021-11-21 Pioneer Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-21-pioneer-preliminary.zip +2021-11-21 Pioneer Premier (16 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-21-pioneer-premier.zip +2021-11-22 Pioneer Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-22-pioneer-challenge.zip +2021-11-22 Pioneer League (23 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-22-pioneer-league.zip +2021-11-25 Pioneer League (15 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-25-pioneer-league.zip +2021-11-25 Pioneer Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-25-pioneer-preliminary.zip +2021-11-26 Pioneer Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/pioneer/2021-11-26-pioneer-preliminary.zip diff --git a/forge-gui/res/lists/net-decks-archive-standard.txt b/forge-gui/res/lists/net-decks-archive-standard.txt index 6423e7eba52..8e7b300e94b 100644 --- a/forge-gui/res/lists/net-decks-archive-standard.txt +++ b/forge-gui/res/lists/net-decks-archive-standard.txt @@ -2530,3 +2530,13 @@ 2021-11-07 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-07-standard-challenge.zip 2021-11-08 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-08-standard-challenge.zip 2021-11-08 Standard League (9 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-08-standard-league.zip +2021-11-11 Standard League (7 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-11-standard-league.zip +2021-11-14 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-14-standard-challenge.zip +2021-11-15 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-15-standard-challenge.zip +2021-11-15 Standard League (10 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-15-standard-league.zip +2021-11-17 Standard Preliminary (5 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-17-standard-preliminary.zip +2021-11-18 Standard League (11 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-18-standard-league.zip +2021-11-21 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-21-standard-challenge.zip +2021-11-22 Standard Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-22-standard-challenge.zip +2021-11-22 Standard League (15 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-22-standard-league.zip +2021-11-25 Standard League (12 decks) | https://downloads.cardforge.org/decks/archive/standard/2021-11-25-standard-league.zip diff --git a/forge-gui/res/lists/net-decks-archive-vintage.txt b/forge-gui/res/lists/net-decks-archive-vintage.txt index ad699c75e9d..d2cf15c347e 100644 --- a/forge-gui/res/lists/net-decks-archive-vintage.txt +++ b/forge-gui/res/lists/net-decks-archive-vintage.txt @@ -1547,3 +1547,13 @@ 2021-11-07 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-07-vintage-challenge.zip 2021-11-07 Vintage League (14 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-07-vintage-league.zip 2021-11-08 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-08-vintage-challenge.zip +2021-11-11 Vintage Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-11-vintage-preliminary.zip +2021-11-13 Vintage Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-13-vintage-preliminary.zip +2021-11-14 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-14-vintage-challenge.zip +2021-11-14 Vintage League (9 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-14-vintage-league.zip +2021-11-15 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-15-vintage-challenge.zip +2021-11-21 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-21-vintage-challenge.zip +2021-11-21 Vintage League (15 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-21-vintage-league.zip +2021-11-22 Vintage Challenge (32 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-22-vintage-challenge.zip +2021-11-23 Vintage Preliminary (4 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-23-vintage-preliminary.zip +2021-11-25 Vintage Preliminary (3 decks) | https://downloads.cardforge.org/decks/archive/vintage/2021-11-25-vintage-preliminary.zip diff --git a/forge-gui/res/quest/booster-prices.txt b/forge-gui/res/quest/booster-prices.txt index a424cc7c1dd..2c4cf4387aa 100644 --- a/forge-gui/res/quest/booster-prices.txt +++ b/forge-gui/res/quest/booster-prices.txt @@ -1,117 +1,117 @@ -Tenth Edition Booster Pack =700 -Unlimited Edition Booster Pack =35000 +Tenth Edition Draft Booster Pack =700 +Unlimited Edition Draft Booster Pack =35000 Unlimited Edition Starter Deck =120000 -Revised Edition Booster Pack =6500 +Revised Edition Draft Booster Pack =6500 Revised Edition Starter Deck =20000 -Fourth Edition Booster Pack =900 +Fourth Edition Draft Booster Pack =900 Fourth Edition Starter Deck =3500 -Fifth Dawn Booster Pack =700 -Fifth Edition Booster Pack =700 +Fifth Dawn Draft Booster Pack =700 +Fifth Edition Draft Booster Pack =700 Fifth Edition Starter Deck =2500 -Classic Sixth Edition Booster Pack =700 +Classic Sixth Edition Draft Booster Pack =700 Classic Sixth Edition Tournament Pack =1500 -Seventh Edition Booster Pack =600 -Eighth Edition Booster Pack =400 -Ninth Edition Booster Pack =400 -Alliances Booster Pack =1600 -Apocalypse Booster Pack =900 -Alara Reborn Booster Pack =600 -Arabian Nights Booster Pack =40000 -Antiquities Booster Pack =10000 -Avacyn Restored Booster Pack =400 -Betrayers of Kamigawa Booster Pack =700 -Born of the Gods Booster Pack =300 -Champions of Kamigawa Booster Pack =1000 +Seventh Edition Draft Booster Pack =600 +Eighth Edition Draft Booster Pack =400 +Ninth Edition Draft Booster Pack =400 +Alliances Draft Booster Pack =1600 +Apocalypse Draft Booster Pack =900 +Alara Reborn Draft Booster Pack =600 +Arabian Nights Draft Booster Pack =40000 +Antiquities Draft Booster Pack =10000 +Avacyn Restored Draft Booster Pack =400 +Betrayers of Kamigawa Draft Booster Pack =700 +Born of the Gods Draft Booster Pack =300 +Champions of Kamigawa Draft Booster Pack =1000 Champions of Kamigawa Tournament Pack =3000 -Chronicles Booster Pack =700 -Conflux Booster Pack =1200 -Coldsnap Booster Pack =700 -Dark Ascension Booster Pack =350 -Darksteel Booster Pack =900 -Dissension Booster Pack =900 -Dragon's Maze Booster Pack =300 -Eventide Booster Pack =1200 -Exodus Booster Pack =900 -Fallen Empires Booster Pack =300 -Future Sight Booster Pack =2000 -Gatecrash Booster Pack =300 -Guildpact Booster Pack =1000 -Homelands Booster Pack =300 -Ice Age Booster Pack =900 +Chronicles Draft Booster Pack =700 +Conflux Draft Booster Pack =1200 +Coldsnap Draft Booster Pack =700 +Dark Ascension Draft Booster Pack =350 +Darksteel Draft Booster Pack =900 +Dissension Draft Booster Pack =900 +Dragon's Maze Draft Booster Pack =300 +Eventide Draft Booster Pack =1200 +Exodus Draft Booster Pack =900 +Fallen Empires Draft Booster Pack =300 +Future Sight Draft Booster Pack =2000 +Gatecrash Draft Booster Pack =300 +Guildpact Draft Booster Pack =1000 +Homelands Draft Booster Pack =300 +Ice Age Draft Booster Pack =900 Ice Age Starter Deck =2500 -Innistrad Booster Pack =600 +Innistrad Draft Booster Pack =600 Chronicles Booster Box =30000 -Invasion Booster Pack =700 +Invasion Draft Booster Pack =700 Invasion Tournament Pack =1800 -Journey into Nyx Booster Pack =300 -Judgment Booster Pack =600 +Journey into Nyx Draft Booster Pack =300 +Judgment Draft Booster Pack =600 Khans of Tarkir =400 -Limited Edition Alpha Booster Pack =75000 +Limited Edition Alpha Draft Booster Pack =75000 Limited Edition Alpha Starter Deck =250000 -Limited Edition Beta Booster Pack =45000 +Limited Edition Beta Draft Booster Pack =45000 Limited Edition Beta Starter Deck =400000 -Legends Booster Pack =15000 -Legions Booster Pack =700 -Lorwyn Booster Pack =1700 +Legends Draft Booster Pack =15000 +Legions Draft Booster Pack =700 +Lorwyn Draft Booster Pack =1700 Lorwyn Tournament Pack =3000 -Magic 2010 Booster Pack =500 -Magic 2011 Booster Pack =350 -Magic 2012 Booster Pack =300 -Magic 2013 Booster Pack =300 -Magic 2014 Booster Pack =300 -Magic 2015 Booster Pack =300 -Mirrodin Besieged Booster Pack =400 -Mirage Booster Pack =1000 +Magic 2010 Draft Booster Pack =500 +Magic 2011 Draft Booster Pack =350 +Magic 2012 Draft Booster Pack =300 +Magic 2013 Draft Booster Pack =300 +Magic 2014 Draft Booster Pack =300 +Magic 2015 Draft Booster Pack =300 +Mirrodin Besieged Draft Booster Pack =400 +Mirage Draft Booster Pack =1000 Mirage Starter Deck =2500 -Mercadian Masques Booster Pack =900 +Mercadian Masques Draft Booster Pack =900 Mercadian Masques Tournament Pack =2000 -Morningtide Booster Pack =1300 -Mirrodin Booster Pack =900 +Morningtide Draft Booster Pack =1300 +Mirrodin Draft Booster Pack =900 Mirrodin Tournament Pack =2500 -Modern Masters Booster Pack =2500 -Nemesis Booster Pack =600 -New Phyrexia Booster Pack =600 -Odyssey Booster Pack =600 +Modern Masters Draft Booster Pack =2500 +Nemesis Draft Booster Pack =600 +New Phyrexia Draft Booster Pack =600 +Odyssey Draft Booster Pack =600 Odyssey Tournament Pack =1500 -Onslaught Booster Pack =1400 +Onslaught Draft Booster Pack =1400 Onslaught Tournament Pack =2000 -Planar Chaos Booster Pack =900 -Planeshift Booster Pack =700 -Portal: Second Age Booster Pack =1200 +Planar Chaos Draft Booster Pack =900 +Planeshift Draft Booster Pack =700 +Portal: Second Age Draft Booster Pack =1200 Portal: Second Age Booster Box =40000 -Portal Booster Pack =1200 +Portal Draft Booster Pack =1200 Portal Booster Box =40000 -Portal: Three Kingdoms Booster Pack =17500 +Portal: Three Kingdoms Draft Booster Pack =17500 Portal: Three Kingdoms Booster Box =600000 -Prophecy Booster Pack =500 -Ravnica: City of Guilds Booster Pack =1500 +Prophecy Draft Booster Pack =500 +Ravnica: City of Guilds Draft Booster Pack =1500 Ravnica: City of Guilds Tournament Pack =3500 -Return to Ravnica Booster Pack =400 -Rise of the Eldrazi Booster Pack =1200 -Saviors of Kamigawa Booster Pack =500 -Scars of Mirrodin Booster Pack =400 -Scourge Booster Pack =600 -Shadowmoor Booster Pack =1500 -Shards of Alara Booster Pack =1000 +Return to Ravnica Draft Booster Pack =400 +Rise of the Eldrazi Draft Booster Pack =1200 +Saviors of Kamigawa Draft Booster Pack =500 +Scars of Mirrodin Draft Booster Pack =400 +Scourge Draft Booster Pack =600 +Shadowmoor Draft Booster Pack =1500 +Shards of Alara Draft Booster Pack =1000 Shards of Alara Tournament Pack =2500 -Starter 1999 Booster Pack =2500 +Starter 1999 Draft Booster Pack =2500 Starter 1999 Booster Box =90000 -Stronghold Booster Pack =900 -Tempest Booster Pack =3000 +Stronghold Draft Booster Pack =900 +Tempest Draft Booster Pack =3000 Tempest Starter Deck =7000 -The Dark Booster Pack =1500 -Theros Booster Pack =300 -Time Spiral Booster Pack =900 +The Dark Draft Booster Pack =1500 +Theros Draft Booster Pack =300 +Time Spiral Draft Booster Pack =900 Time Spiral Tournament Pack =1500 -Torment Booster Pack =600 -Urza's Destiny Booster Pack =1500 -Urza's Legacy Booster Pack =1800 -Urza's Saga Booster Pack =2000 +Torment Draft Booster Pack =600 +Urza's Destiny Draft Booster Pack =1500 +Urza's Legacy Draft Booster Pack =1800 +Urza's Saga Draft Booster Pack =2000 Urza's Saga Tournament Pack =7000 -Visions Booster Pack =1000 -Weatherlight Booster Pack =800 -Worldwake Booster Pack =1500 -Zendikar Booster Pack =1500 +Visions Draft Booster Pack =1000 +Weatherlight Draft Booster Pack =800 +Worldwake Draft Booster Pack =1500 +Zendikar Draft Booster Pack =1500 Limited Edition Alpha Booster Box =2500000 Limited Edition Beta Booster Box =1500000 Unlimited Edition Booster Box =1000000 diff --git a/forge-gui/res/tokenscripts/b_0_0_phyrexian_germ.txt b/forge-gui/res/tokenscripts/b_0_0_phyrexian_germ.txt index 5258fdfc6cb..700f4fa02fb 100644 --- a/forge-gui/res/tokenscripts/b_0_0_phyrexian_germ.txt +++ b/forge-gui/res/tokenscripts/b_0_0_phyrexian_germ.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Germ +Name:Phyrexian Germ Token ManaCost:no cost Types:Creature Phyrexian Germ Colors:black diff --git a/forge-gui/res/tokenscripts/b_0_0_zombie_army.txt b/forge-gui/res/tokenscripts/b_0_0_zombie_army.txt index fe38f336362..c696ec74ab8 100644 --- a/forge-gui/res/tokenscripts/b_0_0_zombie_army.txt +++ b/forge-gui/res/tokenscripts/b_0_0_zombie_army.txt @@ -1,4 +1,4 @@ -Name:Zombie Army +Name:Zombie Army Token ManaCost:no cost Types:Creature Zombie Army Colors:black diff --git a/forge-gui/res/tokenscripts/b_0_1_cleric.txt b/forge-gui/res/tokenscripts/b_0_1_cleric.txt index 21ebfb9f353..56efc9ba613 100644 --- a/forge-gui/res/tokenscripts/b_0_1_cleric.txt +++ b/forge-gui/res/tokenscripts/b_0_1_cleric.txt @@ -1,4 +1,4 @@ -Name:Cleric +Name:Cleric Token ManaCost:no cost Types:Creature Cleric Colors:black diff --git a/forge-gui/res/tokenscripts/b_0_1_insect.txt b/forge-gui/res/tokenscripts/b_0_1_insect.txt index dc49342985e..d8086570f2b 100644 --- a/forge-gui/res/tokenscripts/b_0_1_insect.txt +++ b/forge-gui/res/tokenscripts/b_0_1_insect.txt @@ -1,4 +1,4 @@ -Name:Insect +Name:Insect Token ManaCost:no cost Types:Creature Insect Colors:black diff --git a/forge-gui/res/tokenscripts/b_0_1_serf.txt b/forge-gui/res/tokenscripts/b_0_1_serf.txt index 3663dcadf94..686e0be74f3 100644 --- a/forge-gui/res/tokenscripts/b_0_1_serf.txt +++ b/forge-gui/res/tokenscripts/b_0_1_serf.txt @@ -1,4 +1,4 @@ -Name:Serf +Name:Serf Token ManaCost:no cost Types:Creature Serf Colors:black diff --git a/forge-gui/res/tokenscripts/b_0_1_thrull.txt b/forge-gui/res/tokenscripts/b_0_1_thrull.txt index 5bdcff6ebba..cdca2bfc70a 100644 --- a/forge-gui/res/tokenscripts/b_0_1_thrull.txt +++ b/forge-gui/res/tokenscripts/b_0_1_thrull.txt @@ -1,4 +1,4 @@ -Name:Thrull +Name:Thrull Token ManaCost:no cost Types:Creature Thrull Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_assassin_deathtouch_haste.txt b/forge-gui/res/tokenscripts/b_1_1_assassin_deathtouch_haste.txt index 6ff5132d40e..bc703bd77fa 100644 --- a/forge-gui/res/tokenscripts/b_1_1_assassin_deathtouch_haste.txt +++ b/forge-gui/res/tokenscripts/b_1_1_assassin_deathtouch_haste.txt @@ -1,4 +1,4 @@ -Name:Assassin +Name:Assassin Token ManaCost:no cost Types:Creature Assassin Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_assassin_deathtouch_pwdestroy.txt b/forge-gui/res/tokenscripts/b_1_1_assassin_deathtouch_pwdestroy.txt index b3dd51c3b70..df220c2a174 100644 --- a/forge-gui/res/tokenscripts/b_1_1_assassin_deathtouch_pwdestroy.txt +++ b/forge-gui/res/tokenscripts/b_1_1_assassin_deathtouch_pwdestroy.txt @@ -1,4 +1,4 @@ -Name:Assassin +Name:Assassin Token ManaCost:no cost Types:Creature Assassin Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_assassin_lose_con.txt b/forge-gui/res/tokenscripts/b_1_1_assassin_lose_con.txt index e7029fa8664..33395dfca6f 100644 --- a/forge-gui/res/tokenscripts/b_1_1_assassin_lose_con.txt +++ b/forge-gui/res/tokenscripts/b_1_1_assassin_lose_con.txt @@ -1,4 +1,4 @@ -Name:Assassin +Name:Assassin Token ManaCost:no cost Types:Creature Assassin Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_bat_flying.txt b/forge-gui/res/tokenscripts/b_1_1_bat_flying.txt index e65eb72e78a..8ce9c92fe5a 100644 --- a/forge-gui/res/tokenscripts/b_1_1_bat_flying.txt +++ b/forge-gui/res/tokenscripts/b_1_1_bat_flying.txt @@ -1,4 +1,4 @@ -Name:Bat +Name:Bat Token ManaCost:no cost Types:Creature Bat Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_faerie_rogue_flying.txt b/forge-gui/res/tokenscripts/b_1_1_faerie_rogue_flying.txt index 9a5fc2101ea..12d7bc6db1d 100644 --- a/forge-gui/res/tokenscripts/b_1_1_faerie_rogue_flying.txt +++ b/forge-gui/res/tokenscripts/b_1_1_faerie_rogue_flying.txt @@ -1,4 +1,4 @@ -Name:Faerie Rogue +Name:Faerie Rogue Token ManaCost:no cost Types:Creature Faerie Rogue Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_goblin_rogue.txt b/forge-gui/res/tokenscripts/b_1_1_goblin_rogue.txt index a1c4074e4aa..c719ba3c61b 100644 --- a/forge-gui/res/tokenscripts/b_1_1_goblin_rogue.txt +++ b/forge-gui/res/tokenscripts/b_1_1_goblin_rogue.txt @@ -1,4 +1,4 @@ -Name:Goblin Rogue +Name:Goblin Rogue Token ManaCost:no cost Types:Creature Goblin Rogue Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_harpy_flying.txt b/forge-gui/res/tokenscripts/b_1_1_harpy_flying.txt index 9c9b8f24095..ed694bee8cc 100644 --- a/forge-gui/res/tokenscripts/b_1_1_harpy_flying.txt +++ b/forge-gui/res/tokenscripts/b_1_1_harpy_flying.txt @@ -1,4 +1,4 @@ -Name:Harpy +Name:Harpy Token ManaCost:no cost Types:Creature Harpy Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_insect.txt b/forge-gui/res/tokenscripts/b_1_1_insect.txt index 0f0f1c67662..388da4b351b 100644 --- a/forge-gui/res/tokenscripts/b_1_1_insect.txt +++ b/forge-gui/res/tokenscripts/b_1_1_insect.txt @@ -1,4 +1,4 @@ -Name:Insect +Name:Insect Token ManaCost:no cost Types:Creature Insect Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_minion.txt b/forge-gui/res/tokenscripts/b_1_1_minion.txt index 8d17b4e6b59..e99b9760217 100644 --- a/forge-gui/res/tokenscripts/b_1_1_minion.txt +++ b/forge-gui/res/tokenscripts/b_1_1_minion.txt @@ -1,4 +1,4 @@ -Name:Minion +Name:Minion Token ManaCost:no cost Types:Creature Minion Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_rat.txt b/forge-gui/res/tokenscripts/b_1_1_rat.txt index 2d9cae4dcd2..387550ea478 100644 --- a/forge-gui/res/tokenscripts/b_1_1_rat.txt +++ b/forge-gui/res/tokenscripts/b_1_1_rat.txt @@ -1,4 +1,4 @@ -Name:Rat +Name:Rat Token ManaCost:no cost Types:Creature Rat Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_rat_deathtouch.txt b/forge-gui/res/tokenscripts/b_1_1_rat_deathtouch.txt index 342577637a4..24257716343 100644 --- a/forge-gui/res/tokenscripts/b_1_1_rat_deathtouch.txt +++ b/forge-gui/res/tokenscripts/b_1_1_rat_deathtouch.txt @@ -1,4 +1,4 @@ -Name:Rat +Name:Rat Token ManaCost:no cost Types:Creature Rat Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_skeleton.txt b/forge-gui/res/tokenscripts/b_1_1_skeleton.txt index fccdbf113f7..54d342633f9 100644 --- a/forge-gui/res/tokenscripts/b_1_1_skeleton.txt +++ b/forge-gui/res/tokenscripts/b_1_1_skeleton.txt @@ -1,4 +1,4 @@ -Name:Skeleton +Name:Skeleton Token ManaCost:no cost Types:Creature Skeleton Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_skeleton_opp_life.txt b/forge-gui/res/tokenscripts/b_1_1_skeleton_opp_life.txt index a47e2ae0ce7..f667080d1ae 100644 --- a/forge-gui/res/tokenscripts/b_1_1_skeleton_opp_life.txt +++ b/forge-gui/res/tokenscripts/b_1_1_skeleton_opp_life.txt @@ -1,4 +1,4 @@ -Name:Skeleton +Name:Skeleton Token ManaCost:no cost Types:Creature Minion Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_skeleton_regenerate.txt b/forge-gui/res/tokenscripts/b_1_1_skeleton_regenerate.txt index f09843c07a8..8eeaafda389 100644 --- a/forge-gui/res/tokenscripts/b_1_1_skeleton_regenerate.txt +++ b/forge-gui/res/tokenscripts/b_1_1_skeleton_regenerate.txt @@ -1,4 +1,4 @@ -Name:Skeleton +Name:Skeleton Token ManaCost:no cost Colors:black Types:Creature Skeleton diff --git a/forge-gui/res/tokenscripts/b_1_1_slug.txt b/forge-gui/res/tokenscripts/b_1_1_slug.txt index 151da6be975..dbf6b0705f5 100644 --- a/forge-gui/res/tokenscripts/b_1_1_slug.txt +++ b/forge-gui/res/tokenscripts/b_1_1_slug.txt @@ -1,4 +1,4 @@ -Name:Slug +Name:Slug Token ManaCost:no cost Types:Creature Slug Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_snake_deathtouch.txt b/forge-gui/res/tokenscripts/b_1_1_snake_deathtouch.txt index 47211c756f1..9c886a66816 100644 --- a/forge-gui/res/tokenscripts/b_1_1_snake_deathtouch.txt +++ b/forge-gui/res/tokenscripts/b_1_1_snake_deathtouch.txt @@ -1,4 +1,4 @@ -Name:Snake +Name:Snake Token ManaCost:no cost Types:Creature Snake Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_thrull.txt b/forge-gui/res/tokenscripts/b_1_1_thrull.txt index d6e7c762a64..2c9bdf610d1 100644 --- a/forge-gui/res/tokenscripts/b_1_1_thrull.txt +++ b/forge-gui/res/tokenscripts/b_1_1_thrull.txt @@ -1,4 +1,4 @@ -Name:Thrull +Name:Thrull Token ManaCost:no cost Types:Creature Thrull Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_vampire.txt b/forge-gui/res/tokenscripts/b_1_1_vampire.txt index fd3457204aa..f5ef95a26c1 100644 --- a/forge-gui/res/tokenscripts/b_1_1_vampire.txt +++ b/forge-gui/res/tokenscripts/b_1_1_vampire.txt @@ -1,4 +1,4 @@ -Name:Vampire +Name:Vampire Token ManaCost:no cost Types:Creature Vampire Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_vampire_knight_lifelink.txt b/forge-gui/res/tokenscripts/b_1_1_vampire_knight_lifelink.txt index b86858c2dd7..4da021eeffb 100644 --- a/forge-gui/res/tokenscripts/b_1_1_vampire_knight_lifelink.txt +++ b/forge-gui/res/tokenscripts/b_1_1_vampire_knight_lifelink.txt @@ -1,4 +1,4 @@ -Name:Vampire Knight +Name:Vampire Knight Token ManaCost:no cost Types:Creature Vampire Knight Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_vampire_lifelink.txt b/forge-gui/res/tokenscripts/b_1_1_vampire_lifelink.txt index 5f327a7ef68..5ea01970e47 100644 --- a/forge-gui/res/tokenscripts/b_1_1_vampire_lifelink.txt +++ b/forge-gui/res/tokenscripts/b_1_1_vampire_lifelink.txt @@ -1,4 +1,4 @@ -Name:Vampire +Name:Vampire Token ManaCost:no cost Types:Creature Vampire Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_1_wolf_deathtouch.txt b/forge-gui/res/tokenscripts/b_1_1_wolf_deathtouch.txt index 662f87aee5c..c9b44a7fc5b 100644 --- a/forge-gui/res/tokenscripts/b_1_1_wolf_deathtouch.txt +++ b/forge-gui/res/tokenscripts/b_1_1_wolf_deathtouch.txt @@ -1,4 +1,4 @@ -Name:Wolf +Name:Wolf Token ManaCost:no cost Types:Creature Wolf Colors:black diff --git a/forge-gui/res/tokenscripts/b_1_2_bat_flying_nosferatu.txt b/forge-gui/res/tokenscripts/b_1_2_bat_flying_nosferatu.txt index 3aa7782d2dc..eef38983faf 100644 --- a/forge-gui/res/tokenscripts/b_1_2_bat_flying_nosferatu.txt +++ b/forge-gui/res/tokenscripts/b_1_2_bat_flying_nosferatu.txt @@ -1,4 +1,4 @@ -Name:Bat +Name:Bat Token ManaCost:no cost Types:Creature Bat Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_1_cat.txt b/forge-gui/res/tokenscripts/b_2_1_cat.txt index bda7aed31b3..2a1672e3c0c 100644 --- a/forge-gui/res/tokenscripts/b_2_1_cat.txt +++ b/forge-gui/res/tokenscripts/b_2_1_cat.txt @@ -1,4 +1,4 @@ -Name:Cat +Name:Cat Token ManaCost:no cost Types:Creature Cat Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_1_spider_menace_reach.txt b/forge-gui/res/tokenscripts/b_2_1_spider_menace_reach.txt index 7566abf8dc2..58ee9448c6b 100644 --- a/forge-gui/res/tokenscripts/b_2_1_spider_menace_reach.txt +++ b/forge-gui/res/tokenscripts/b_2_1_spider_menace_reach.txt @@ -1,4 +1,4 @@ -Name:Spider +Name:Spider Token ManaCost:no cost Types:Creature Spider Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_1_warrior.txt b/forge-gui/res/tokenscripts/b_2_1_warrior.txt index 3e197e56f26..d3080fd6bea 100644 --- a/forge-gui/res/tokenscripts/b_2_1_warrior.txt +++ b/forge-gui/res/tokenscripts/b_2_1_warrior.txt @@ -1,4 +1,4 @@ -Name:Warrior +Name:Warrior Token ManaCost:no cost Types:Creature Warrior Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_e_zombie.txt b/forge-gui/res/tokenscripts/b_2_2_e_zombie.txt index 44a36afa109..34ed124c315 100644 --- a/forge-gui/res/tokenscripts/b_2_2_e_zombie.txt +++ b/forge-gui/res/tokenscripts/b_2_2_e_zombie.txt @@ -1,4 +1,4 @@ -Name:Zombie +Name:Zombie Token ManaCost:no cost Types:Enchantment Creature Zombie Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_knight_flanking_pro_white_haste.txt b/forge-gui/res/tokenscripts/b_2_2_knight_flanking_pro_white_haste.txt index 14e11cae9df..da2080a8906 100644 --- a/forge-gui/res/tokenscripts/b_2_2_knight_flanking_pro_white_haste.txt +++ b/forge-gui/res/tokenscripts/b_2_2_knight_flanking_pro_white_haste.txt @@ -1,4 +1,4 @@ -Name:Knight +Name:Knight Token ManaCost:no cost Types:Creature Knight Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_phyrexian_zombie.txt b/forge-gui/res/tokenscripts/b_2_2_phyrexian_zombie.txt index 1e370961316..d2027b8c11e 100644 --- a/forge-gui/res/tokenscripts/b_2_2_phyrexian_zombie.txt +++ b/forge-gui/res/tokenscripts/b_2_2_phyrexian_zombie.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Zombie +Name:Phyrexian Zombie Token ManaCost:no cost Types:Creature Phyrexian Zombie Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_pirate_menace.txt b/forge-gui/res/tokenscripts/b_2_2_pirate_menace.txt index 144272a2442..05a63ece5a5 100644 --- a/forge-gui/res/tokenscripts/b_2_2_pirate_menace.txt +++ b/forge-gui/res/tokenscripts/b_2_2_pirate_menace.txt @@ -1,4 +1,4 @@ -Name:Pirate +Name:Pirate Token ManaCost:no cost Types:Creature Pirate Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_rogue_hexproof.txt b/forge-gui/res/tokenscripts/b_2_2_rogue_hexproof.txt index f955c8ab238..132ba0a0e8b 100644 --- a/forge-gui/res/tokenscripts/b_2_2_rogue_hexproof.txt +++ b/forge-gui/res/tokenscripts/b_2_2_rogue_hexproof.txt @@ -1,4 +1,4 @@ -Name:Rogue +Name:Rogue Token ManaCost:no cost Types:Creature Rogue Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_rogue_menace.txt b/forge-gui/res/tokenscripts/b_2_2_rogue_menace.txt index f0203ee990b..6492fd8a214 100644 --- a/forge-gui/res/tokenscripts/b_2_2_rogue_menace.txt +++ b/forge-gui/res/tokenscripts/b_2_2_rogue_menace.txt @@ -1,4 +1,4 @@ -Name:Rogue +Name:Rogue Token ManaCost:no cost Types:Creature Rogue Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_vampire_flying.txt b/forge-gui/res/tokenscripts/b_2_2_vampire_flying.txt index 6a6063b72ec..5fe2b07f3c5 100644 --- a/forge-gui/res/tokenscripts/b_2_2_vampire_flying.txt +++ b/forge-gui/res/tokenscripts/b_2_2_vampire_flying.txt @@ -1,4 +1,4 @@ -Name:Vampire +Name:Vampire Token ManaCost:no cost Types:Creature Vampire Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_zombie.txt b/forge-gui/res/tokenscripts/b_2_2_zombie.txt index dc060486fbe..0437d753a82 100644 --- a/forge-gui/res/tokenscripts/b_2_2_zombie.txt +++ b/forge-gui/res/tokenscripts/b_2_2_zombie.txt @@ -1,4 +1,4 @@ -Name:Zombie +Name:Zombie Token ManaCost:no cost Types:Creature Zombie Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_zombie_berserker.txt b/forge-gui/res/tokenscripts/b_2_2_zombie_berserker.txt index feefcaf2501..02b90bce740 100644 --- a/forge-gui/res/tokenscripts/b_2_2_zombie_berserker.txt +++ b/forge-gui/res/tokenscripts/b_2_2_zombie_berserker.txt @@ -1,4 +1,4 @@ -Name:Zombie Berserker +Name:Zombie Berserker Token ManaCost:no cost Types:Creature Zombie Berserker Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_zombie_decayed.txt b/forge-gui/res/tokenscripts/b_2_2_zombie_decayed.txt index 095b3b04cf1..33a1b7e03e6 100644 --- a/forge-gui/res/tokenscripts/b_2_2_zombie_decayed.txt +++ b/forge-gui/res/tokenscripts/b_2_2_zombie_decayed.txt @@ -1,4 +1,4 @@ -Name:Zombie +Name:Zombie Token ManaCost:no cost Types:Creature Zombie Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_zombie_designated.txt b/forge-gui/res/tokenscripts/b_2_2_zombie_designated.txt index 38cf52ad958..0d2be86d6b4 100644 --- a/forge-gui/res/tokenscripts/b_2_2_zombie_designated.txt +++ b/forge-gui/res/tokenscripts/b_2_2_zombie_designated.txt @@ -1,4 +1,4 @@ -Name:Zombie +Name:Zombie Token ManaCost:no cost Types:Creature Zombie Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_2_zombie_knight_menace.txt b/forge-gui/res/tokenscripts/b_2_2_zombie_knight_menace.txt index f234aa306f8..fcbd7a0b844 100644 --- a/forge-gui/res/tokenscripts/b_2_2_zombie_knight_menace.txt +++ b/forge-gui/res/tokenscripts/b_2_2_zombie_knight_menace.txt @@ -1,4 +1,4 @@ -Name:Zombie Knight +Name:Zombie Knight Token ManaCost:no cost Types:Creature Zombie Knight Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_3_vampire_flying_lifelink.txt b/forge-gui/res/tokenscripts/b_2_3_vampire_flying_lifelink.txt index 87ec10ae959..cc9f5915c42 100644 --- a/forge-gui/res/tokenscripts/b_2_3_vampire_flying_lifelink.txt +++ b/forge-gui/res/tokenscripts/b_2_3_vampire_flying_lifelink.txt @@ -1,4 +1,4 @@ -Name:Vampire +Name:Vampire Token ManaCost:no cost Types:Creature Vampire Colors:black diff --git a/forge-gui/res/tokenscripts/b_2_4_spider_reach.txt b/forge-gui/res/tokenscripts/b_2_4_spider_reach.txt index 16f506e7ed9..95958401cfe 100644 --- a/forge-gui/res/tokenscripts/b_2_4_spider_reach.txt +++ b/forge-gui/res/tokenscripts/b_2_4_spider_reach.txt @@ -1,4 +1,4 @@ -Name:Spider +Name:Spider Token ManaCost:no cost Types:Creature Spider Colors:black diff --git a/forge-gui/res/tokenscripts/b_3_3_angel_flying.txt b/forge-gui/res/tokenscripts/b_3_3_angel_flying.txt index 7a85f159e5a..90ee2ff1f38 100644 --- a/forge-gui/res/tokenscripts/b_3_3_angel_flying.txt +++ b/forge-gui/res/tokenscripts/b_3_3_angel_flying.txt @@ -1,4 +1,4 @@ -Name:Angel +Name:Angel Token ManaCost:no cost Types:Creature Angel Colors:black diff --git a/forge-gui/res/tokenscripts/b_3_3_beast_deathtouch.txt b/forge-gui/res/tokenscripts/b_3_3_beast_deathtouch.txt index 58e3d012ec9..1ca12c0f5b1 100644 --- a/forge-gui/res/tokenscripts/b_3_3_beast_deathtouch.txt +++ b/forge-gui/res/tokenscripts/b_3_3_beast_deathtouch.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token ManaCost:no cost Types:Creature Beast Colors:black diff --git a/forge-gui/res/tokenscripts/b_3_3_horror.txt b/forge-gui/res/tokenscripts/b_3_3_horror.txt index cd152ec7d8a..6c00b1315c5 100644 --- a/forge-gui/res/tokenscripts/b_3_3_horror.txt +++ b/forge-gui/res/tokenscripts/b_3_3_horror.txt @@ -1,4 +1,4 @@ -Name:Horror +Name:Horror Token ManaCost:no cost Types:Creature Horror Colors:black diff --git a/forge-gui/res/tokenscripts/b_3_3_horror_designated.txt b/forge-gui/res/tokenscripts/b_3_3_horror_designated.txt index 75a3338092e..b1e991d227d 100644 --- a/forge-gui/res/tokenscripts/b_3_3_horror_designated.txt +++ b/forge-gui/res/tokenscripts/b_3_3_horror_designated.txt @@ -1,4 +1,4 @@ -Name:Horror +Name:Horror Token ManaCost:no cost Types:Creature Horror Colors:black diff --git a/forge-gui/res/tokenscripts/b_3_3_kavu.txt b/forge-gui/res/tokenscripts/b_3_3_kavu.txt index f5de68d353f..f0638ab5d22 100644 --- a/forge-gui/res/tokenscripts/b_3_3_kavu.txt +++ b/forge-gui/res/tokenscripts/b_3_3_kavu.txt @@ -1,4 +1,4 @@ -Name:Kavu +Name:Kavu Token ManaCost:no cost Types:Creature Kavu Colors:black diff --git a/forge-gui/res/tokenscripts/b_4_4_horror.txt b/forge-gui/res/tokenscripts/b_4_4_horror.txt index d97ada87439..e44c8a44cc9 100644 --- a/forge-gui/res/tokenscripts/b_4_4_horror.txt +++ b/forge-gui/res/tokenscripts/b_4_4_horror.txt @@ -1,4 +1,4 @@ -Name:Horror +Name:Horror Token ManaCost:no cost Types:Creature Horror Colors:black diff --git a/forge-gui/res/tokenscripts/b_4_4_zombie_warrior_vigilance.txt b/forge-gui/res/tokenscripts/b_4_4_zombie_warrior_vigilance.txt index 781a366b2f3..8e04af9871e 100644 --- a/forge-gui/res/tokenscripts/b_4_4_zombie_warrior_vigilance.txt +++ b/forge-gui/res/tokenscripts/b_4_4_zombie_warrior_vigilance.txt @@ -1,4 +1,4 @@ -Name:Zombie Warrior +Name:Zombie Warrior Token ManaCost:no cost Types:Creature Zombie Warrior Colors:black diff --git a/forge-gui/res/tokenscripts/b_5_5_demon_flying.txt b/forge-gui/res/tokenscripts/b_5_5_demon_flying.txt index 043f8af2003..68f6fa690a6 100644 --- a/forge-gui/res/tokenscripts/b_5_5_demon_flying.txt +++ b/forge-gui/res/tokenscripts/b_5_5_demon_flying.txt @@ -1,4 +1,4 @@ -Name:Demon +Name:Demon Token ManaCost:no cost Types:Creature Demon Colors:black diff --git a/forge-gui/res/tokenscripts/b_5_5_zombie_giant.txt b/forge-gui/res/tokenscripts/b_5_5_zombie_giant.txt index e63ce5f05e8..ca86e66e86b 100644 --- a/forge-gui/res/tokenscripts/b_5_5_zombie_giant.txt +++ b/forge-gui/res/tokenscripts/b_5_5_zombie_giant.txt @@ -1,4 +1,4 @@ -Name:Zombie Giant +Name:Zombie Giant Token ManaCost:no cost Types:Creature Zombie Giant Colors:black diff --git a/forge-gui/res/tokenscripts/b_6_6_demon_flying_trample_aristocrat.txt b/forge-gui/res/tokenscripts/b_6_6_demon_flying_trample_aristocrat.txt index c1f90ace98c..627d0801b55 100644 --- a/forge-gui/res/tokenscripts/b_6_6_demon_flying_trample_aristocrat.txt +++ b/forge-gui/res/tokenscripts/b_6_6_demon_flying_trample_aristocrat.txt @@ -1,4 +1,4 @@ -Name:Demon +Name:Demon Token ManaCost:no cost Types:Creature Demon Colors:black diff --git a/forge-gui/res/tokenscripts/b_6_6_wurm_trample.txt b/forge-gui/res/tokenscripts/b_6_6_wurm_trample.txt index 9c26bc34b4c..8a57f4479df 100644 --- a/forge-gui/res/tokenscripts/b_6_6_wurm_trample.txt +++ b/forge-gui/res/tokenscripts/b_6_6_wurm_trample.txt @@ -1,4 +1,4 @@ -Name:Wurm +Name:Wurm Token ManaCost:no cost Types:Creature Wurm Colors:black diff --git a/forge-gui/res/tokenscripts/b_aura_curse_life.txt b/forge-gui/res/tokenscripts/b_aura_curse_life.txt index 625ad6ba862..1d344901e67 100644 --- a/forge-gui/res/tokenscripts/b_aura_curse_life.txt +++ b/forge-gui/res/tokenscripts/b_aura_curse_life.txt @@ -1,4 +1,4 @@ -Name:Aura Curse +Name:Aura Curse Token ManaCost:no cost Types:Enchantment Aura Curse Colors:black diff --git a/forge-gui/res/tokenscripts/b_x_x_demon_flying.txt b/forge-gui/res/tokenscripts/b_x_x_demon_flying.txt index 84cafe5aeb1..849edf7b3d9 100644 --- a/forge-gui/res/tokenscripts/b_x_x_demon_flying.txt +++ b/forge-gui/res/tokenscripts/b_x_x_demon_flying.txt @@ -1,4 +1,4 @@ -Name:Demon +Name:Demon Token ManaCost:no cost Colors:black Types:Creature Demon diff --git a/forge-gui/res/tokenscripts/b_x_x_horror.txt b/forge-gui/res/tokenscripts/b_x_x_horror.txt index 15ca8576237..e94ec5f6656 100644 --- a/forge-gui/res/tokenscripts/b_x_x_horror.txt +++ b/forge-gui/res/tokenscripts/b_x_x_horror.txt @@ -1,4 +1,4 @@ -Name:Horror +Name:Horror Token ManaCost:no cost Colors:black Types:Creature Horror diff --git a/forge-gui/res/tokenscripts/b_x_x_nightmare_horror.txt b/forge-gui/res/tokenscripts/b_x_x_nightmare_horror.txt index ed285ddcf61..a37f5d06905 100644 --- a/forge-gui/res/tokenscripts/b_x_x_nightmare_horror.txt +++ b/forge-gui/res/tokenscripts/b_x_x_nightmare_horror.txt @@ -1,4 +1,4 @@ -Name:Nightmare Horror +Name:Nightmare Horror Token ManaCost:no cost Colors:black Types:Creature Nightmare Horror diff --git a/forge-gui/res/tokenscripts/b_x_x_phyrexian_minion.txt b/forge-gui/res/tokenscripts/b_x_x_phyrexian_minion.txt index a3586a686d8..ac0b3850960 100644 --- a/forge-gui/res/tokenscripts/b_x_x_phyrexian_minion.txt +++ b/forge-gui/res/tokenscripts/b_x_x_phyrexian_minion.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Minion +Name:Phyrexian Minion Token ManaCost:no cost Types:Creature Phyrexian Minion PT:*/* diff --git a/forge-gui/res/tokenscripts/b_x_x_spirit.txt b/forge-gui/res/tokenscripts/b_x_x_spirit.txt index 9caae9a22b6..1db6e9dc9c8 100644 --- a/forge-gui/res/tokenscripts/b_x_x_spirit.txt +++ b/forge-gui/res/tokenscripts/b_x_x_spirit.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Colors:black Types:Creature Spirit diff --git a/forge-gui/res/tokenscripts/b_x_x_vampire.txt b/forge-gui/res/tokenscripts/b_x_x_vampire.txt index 80bc25b2bf0..425094f4393 100644 --- a/forge-gui/res/tokenscripts/b_x_x_vampire.txt +++ b/forge-gui/res/tokenscripts/b_x_x_vampire.txt @@ -1,4 +1,4 @@ -Name:Vampire +Name:Vampire Token ManaCost:no cost Colors:black Types:Creature Vampire diff --git a/forge-gui/res/tokenscripts/b_x_x_zombie.txt b/forge-gui/res/tokenscripts/b_x_x_zombie.txt index 0446ebb2a3d..8daee75f419 100644 --- a/forge-gui/res/tokenscripts/b_x_x_zombie.txt +++ b/forge-gui/res/tokenscripts/b_x_x_zombie.txt @@ -1,4 +1,4 @@ -Name:Zombie +Name:Zombie Token ManaCost:no cost Colors:black Types:Creature Zombie diff --git a/forge-gui/res/tokenscripts/b_x_x_zombie_horror.txt b/forge-gui/res/tokenscripts/b_x_x_zombie_horror.txt index fbd2f188b2e..1a1c8c35ddb 100644 --- a/forge-gui/res/tokenscripts/b_x_x_zombie_horror.txt +++ b/forge-gui/res/tokenscripts/b_x_x_zombie_horror.txt @@ -1,4 +1,4 @@ -Name:Zombie Horror +Name:Zombie Horror Token ManaCost:no cost Colors:black Types:Creature Zombie Horror diff --git a/forge-gui/res/tokenscripts/bg_1_1_e_snake_deathtouch.txt b/forge-gui/res/tokenscripts/bg_1_1_e_snake_deathtouch.txt index 966d195a4cb..1a0e49e2295 100644 --- a/forge-gui/res/tokenscripts/bg_1_1_e_snake_deathtouch.txt +++ b/forge-gui/res/tokenscripts/bg_1_1_e_snake_deathtouch.txt @@ -1,4 +1,4 @@ -Name:Snake +Name:Snake Token ManaCost:no cost Types:Enchantment Creature Snake Colors:black,green diff --git a/forge-gui/res/tokenscripts/bg_1_1_insect.txt b/forge-gui/res/tokenscripts/bg_1_1_insect.txt index 844c2077172..7a340dfa07d 100644 --- a/forge-gui/res/tokenscripts/bg_1_1_insect.txt +++ b/forge-gui/res/tokenscripts/bg_1_1_insect.txt @@ -1,4 +1,4 @@ -Name:Insect +Name:Insect Token ManaCost:no cost Types:Creature Insect Colors:black,green diff --git a/forge-gui/res/tokenscripts/bg_1_1_pest_lifegain.txt b/forge-gui/res/tokenscripts/bg_1_1_pest_lifegain.txt index 82373d0c0e2..a0d7d5323b7 100644 --- a/forge-gui/res/tokenscripts/bg_1_1_pest_lifegain.txt +++ b/forge-gui/res/tokenscripts/bg_1_1_pest_lifegain.txt @@ -1,4 +1,4 @@ -Name:Pest +Name:Pest Token ManaCost:no cost Types:Creature Pest Colors:black,green diff --git a/forge-gui/res/tokenscripts/bg_1_1_worm.txt b/forge-gui/res/tokenscripts/bg_1_1_worm.txt index cbab3b74363..8cb707b5ba2 100644 --- a/forge-gui/res/tokenscripts/bg_1_1_worm.txt +++ b/forge-gui/res/tokenscripts/bg_1_1_worm.txt @@ -1,4 +1,4 @@ -Name:Worm +Name:Worm Token ManaCost:no cost Types:Creature Worm Colors:black,green diff --git a/forge-gui/res/tokenscripts/bg_2_2_wolf_garruk.txt b/forge-gui/res/tokenscripts/bg_2_2_wolf_garruk.txt index 6f5aeeb6a74..4a1d19407b7 100644 --- a/forge-gui/res/tokenscripts/bg_2_2_wolf_garruk.txt +++ b/forge-gui/res/tokenscripts/bg_2_2_wolf_garruk.txt @@ -1,4 +1,4 @@ -Name:Wolf +Name:Wolf Token ManaCost:no cost Types:Creature Wolf Colors:black,green diff --git a/forge-gui/res/tokenscripts/bg_x_x_hydra.txt b/forge-gui/res/tokenscripts/bg_x_x_hydra.txt index 512f9b800ea..be0b476ba65 100644 --- a/forge-gui/res/tokenscripts/bg_x_x_hydra.txt +++ b/forge-gui/res/tokenscripts/bg_x_x_hydra.txt @@ -1,4 +1,4 @@ -Name:Hydra +Name:Hydra Token ManaCost:no cost Colors:black,green Types:Creature Hydra diff --git a/forge-gui/res/tokenscripts/bg_x_x_spirit_warrior.txt b/forge-gui/res/tokenscripts/bg_x_x_spirit_warrior.txt index 3fb466b1cbd..470978cc033 100644 --- a/forge-gui/res/tokenscripts/bg_x_x_spirit_warrior.txt +++ b/forge-gui/res/tokenscripts/bg_x_x_spirit_warrior.txt @@ -1,4 +1,4 @@ -Name:Spirit Warrior +Name:Spirit Warrior Token ManaCost:no cost Colors:black,green Types:Creature Spirit Warrior diff --git a/forge-gui/res/tokenscripts/br_3_1_graveborn_haste.txt b/forge-gui/res/tokenscripts/br_3_1_graveborn_haste.txt index 769e87b3f36..b1bc87bf230 100644 --- a/forge-gui/res/tokenscripts/br_3_1_graveborn_haste.txt +++ b/forge-gui/res/tokenscripts/br_3_1_graveborn_haste.txt @@ -1,4 +1,4 @@ -Name:Graveborn +Name:Graveborn Token ManaCost:no cost Types:Creature Graveborn Colors:black,red diff --git a/forge-gui/res/tokenscripts/br_3_1_vampire_trample_lifelink_haste.txt b/forge-gui/res/tokenscripts/br_3_1_vampire_trample_lifelink_haste.txt index 77aa5f360b7..c4902ff1295 100644 --- a/forge-gui/res/tokenscripts/br_3_1_vampire_trample_lifelink_haste.txt +++ b/forge-gui/res/tokenscripts/br_3_1_vampire_trample_lifelink_haste.txt @@ -1,4 +1,4 @@ -Name:Vampire +Name:Vampire Token ManaCost:no cost Types:Creature Vampire Colors:black,red diff --git a/forge-gui/res/tokenscripts/br_3_6_avatar_haste_bolt.txt b/forge-gui/res/tokenscripts/br_3_6_avatar_haste_bolt.txt index d5f60104cda..8205004f8bd 100644 --- a/forge-gui/res/tokenscripts/br_3_6_avatar_haste_bolt.txt +++ b/forge-gui/res/tokenscripts/br_3_6_avatar_haste_bolt.txt @@ -1,4 +1,4 @@ -Name:Avatar +Name:Avatar Token ManaCost:no cost Types:Creature Avatar Colors:black,red diff --git a/forge-gui/res/tokenscripts/br_5_5_elemental.txt b/forge-gui/res/tokenscripts/br_5_5_elemental.txt index 88d58b6b33e..bd7217429dc 100644 --- a/forge-gui/res/tokenscripts/br_5_5_elemental.txt +++ b/forge-gui/res/tokenscripts/br_5_5_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:black,red diff --git a/forge-gui/res/tokenscripts/brg_3_3_cat_dragon_flying.txt b/forge-gui/res/tokenscripts/brg_3_3_cat_dragon_flying.txt index 32223317439..c8d9f81aca0 100644 --- a/forge-gui/res/tokenscripts/brg_3_3_cat_dragon_flying.txt +++ b/forge-gui/res/tokenscripts/brg_3_3_cat_dragon_flying.txt @@ -1,4 +1,4 @@ -Name:Cat Dragon +Name:Cat Dragon Token ManaCost:no cost Types:Creature Cat Dragon Colors:black,red,green diff --git a/forge-gui/res/tokenscripts/c_0_0_a_construct_total_artifacts.txt b/forge-gui/res/tokenscripts/c_0_0_a_construct_total_artifacts.txt index d1d23030889..ba7959637e5 100644 --- a/forge-gui/res/tokenscripts/c_0_0_a_construct_total_artifacts.txt +++ b/forge-gui/res/tokenscripts/c_0_0_a_construct_total_artifacts.txt @@ -1,4 +1,4 @@ -Name:Construct +Name:Construct Token ManaCost:no cost PT:0/0 Types:Artifact Creature Construct diff --git a/forge-gui/res/tokenscripts/c_0_1_a_egg.txt b/forge-gui/res/tokenscripts/c_0_1_a_egg.txt index 1517d04841b..f30b59fe618 100644 --- a/forge-gui/res/tokenscripts/c_0_1_a_egg.txt +++ b/forge-gui/res/tokenscripts/c_0_1_a_egg.txt @@ -1,4 +1,4 @@ -Name:Egg +Name:Egg Token ManaCost:no cost PT:0/1 Types:Artifact Creature Egg diff --git a/forge-gui/res/tokenscripts/c_0_1_a_goblin_construct_noblock_ping.txt b/forge-gui/res/tokenscripts/c_0_1_a_goblin_construct_noblock_ping.txt index 1e3ad1c6644..3d4bc3e2515 100644 --- a/forge-gui/res/tokenscripts/c_0_1_a_goblin_construct_noblock_ping.txt +++ b/forge-gui/res/tokenscripts/c_0_1_a_goblin_construct_noblock_ping.txt @@ -1,4 +1,4 @@ -Name:Goblin Construct +Name:Goblin Construct Token ManaCost:no cost PT:0/1 Types:Artifact Creature Goblin Construct diff --git a/forge-gui/res/tokenscripts/c_0_1_a_pest.txt b/forge-gui/res/tokenscripts/c_0_1_a_pest.txt index fbbad391b77..9625eef8b10 100644 --- a/forge-gui/res/tokenscripts/c_0_1_a_pest.txt +++ b/forge-gui/res/tokenscripts/c_0_1_a_pest.txt @@ -1,4 +1,4 @@ -Name:Pest +Name:Pest Token ManaCost:no cost PT:0/1 Types:Artifact Creature Pest diff --git a/forge-gui/res/tokenscripts/c_0_1_a_prism.txt b/forge-gui/res/tokenscripts/c_0_1_a_prism.txt index 9fe74dc50cb..801d28d4478 100644 --- a/forge-gui/res/tokenscripts/c_0_1_a_prism.txt +++ b/forge-gui/res/tokenscripts/c_0_1_a_prism.txt @@ -1,4 +1,4 @@ -Name:Prism +Name:Prism Token ManaCost:no cost PT:0/1 Types:Artifact Creature Prism diff --git a/forge-gui/res/tokenscripts/c_0_1_eldrazi_spawn_sac.txt b/forge-gui/res/tokenscripts/c_0_1_eldrazi_spawn_sac.txt index cb9faa44644..4bfa09426c4 100644 --- a/forge-gui/res/tokenscripts/c_0_1_eldrazi_spawn_sac.txt +++ b/forge-gui/res/tokenscripts/c_0_1_eldrazi_spawn_sac.txt @@ -1,4 +1,4 @@ -Name:Eldrazi Spawn +Name:Eldrazi Spawn Token ManaCost:no cost PT:0/1 Types:Creature Eldrazi Spawn diff --git a/forge-gui/res/tokenscripts/c_0_2_a_wall_defender.txt b/forge-gui/res/tokenscripts/c_0_2_a_wall_defender.txt index e2025941895..161da7acf8e 100644 --- a/forge-gui/res/tokenscripts/c_0_2_a_wall_defender.txt +++ b/forge-gui/res/tokenscripts/c_0_2_a_wall_defender.txt @@ -1,4 +1,4 @@ -Name:Wall +Name:Wall Token ManaCost:no cost PT:0/2 Types:Artifact Creature Wall diff --git a/forge-gui/res/tokenscripts/c_0_4_a_wall_defender.txt b/forge-gui/res/tokenscripts/c_0_4_a_wall_defender.txt index 2b5be99e3e2..f7714993830 100644 --- a/forge-gui/res/tokenscripts/c_0_4_a_wall_defender.txt +++ b/forge-gui/res/tokenscripts/c_0_4_a_wall_defender.txt @@ -1,4 +1,4 @@ -Name:Wall +Name:Wall Token ManaCost:no cost Types:Artifact Creature Wall PT:0/4 diff --git a/forge-gui/res/tokenscripts/c_10_10_eldrazi.txt b/forge-gui/res/tokenscripts/c_10_10_eldrazi.txt index b828119a422..72c7cffe385 100644 --- a/forge-gui/res/tokenscripts/c_10_10_eldrazi.txt +++ b/forge-gui/res/tokenscripts/c_10_10_eldrazi.txt @@ -1,4 +1,4 @@ -Name:Eldrazi +Name:Eldrazi Token ManaCost:no cost PT:10/10 Types:Creature Eldrazi diff --git a/forge-gui/res/tokenscripts/c_1_1_a_construct.txt b/forge-gui/res/tokenscripts/c_1_1_a_construct.txt index eeea124b2e0..ac9c60040bb 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_construct.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_construct.txt @@ -1,4 +1,4 @@ -Name:Construct +Name:Construct Token ManaCost:no cost PT:1/1 Types:Artifact Creature Construct diff --git a/forge-gui/res/tokenscripts/c_1_1_a_construct_defender.txt b/forge-gui/res/tokenscripts/c_1_1_a_construct_defender.txt index 9b1fa6fe1c8..5e1fa23b513 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_construct_defender.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_construct_defender.txt @@ -1,4 +1,4 @@ -Name:Construct +Name:Construct Token ManaCost:no cost PT:1/1 Types:Artifact Creature Construct diff --git a/forge-gui/res/tokenscripts/c_1_1_a_gnome.txt b/forge-gui/res/tokenscripts/c_1_1_a_gnome.txt index 107f12cf528..7de28d66709 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_gnome.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_gnome.txt @@ -1,4 +1,4 @@ -Name:Gnome +Name:Gnome Token ManaCost:no cost PT:1/1 Types:Artifact Creature Gnome diff --git a/forge-gui/res/tokenscripts/c_1_1_a_myr.txt b/forge-gui/res/tokenscripts/c_1_1_a_myr.txt index 86c73017cd5..20c86ccd55a 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_myr.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_myr.txt @@ -1,4 +1,4 @@ -Name:Myr +Name:Myr Token ManaCost:no cost PT:1/1 Types:Artifact Creature Myr diff --git a/forge-gui/res/tokenscripts/c_1_1_a_pentavite_flying.txt b/forge-gui/res/tokenscripts/c_1_1_a_pentavite_flying.txt index 087c7158426..e1a2891bf77 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_pentavite_flying.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_pentavite_flying.txt @@ -1,4 +1,4 @@ -Name:Pentavite +Name:Pentavite Token ManaCost:no cost Types:Token Artifact Creature Pentavite PT:1/1 diff --git a/forge-gui/res/tokenscripts/c_1_1_a_phyrexian_myr.txt b/forge-gui/res/tokenscripts/c_1_1_a_phyrexian_myr.txt index 67593e2184c..2a5e890295c 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_phyrexian_myr.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_phyrexian_myr.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Myr +Name:Phyrexian Myr Token ManaCost:no cost PT:1/1 Types:Artifact Creature Phyrexian Myr diff --git a/forge-gui/res/tokenscripts/c_1_1_a_servo.txt b/forge-gui/res/tokenscripts/c_1_1_a_servo.txt index 2a308811418..346b023fb6d 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_servo.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_servo.txt @@ -1,4 +1,4 @@ -Name:Servo +Name:Servo Token ManaCost:no cost Types:Artifact Creature Servo PT:1/1 diff --git a/forge-gui/res/tokenscripts/c_1_1_a_snake_poison.txt b/forge-gui/res/tokenscripts/c_1_1_a_snake_poison.txt index d4903eaba7c..a9d77f9cfb7 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_snake_poison.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_snake_poison.txt @@ -1,4 +1,4 @@ -Name:Snake +Name:Snake Token ManaCost:no cost Types:Artifact Creature Snake PT:1/1 diff --git a/forge-gui/res/tokenscripts/c_1_1_a_tetravite_flying_noenchant.txt b/forge-gui/res/tokenscripts/c_1_1_a_tetravite_flying_noenchant.txt index 9a0712a2c90..328ba974e61 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_tetravite_flying_noenchant.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_tetravite_flying_noenchant.txt @@ -1,4 +1,4 @@ -Name:Tetravite +Name:Tetravite Token ManaCost:no cost Types:Token Artifact Creature Tetravite PT:1/1 diff --git a/forge-gui/res/tokenscripts/c_1_1_a_thopter_flying.txt b/forge-gui/res/tokenscripts/c_1_1_a_thopter_flying.txt index 3a93b1302f9..719482701b2 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_thopter_flying.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_thopter_flying.txt @@ -1,4 +1,4 @@ -Name:Thopter +Name:Thopter Token ManaCost:no cost Types:Artifact Creature Thopter Colors:colorless diff --git a/forge-gui/res/tokenscripts/c_1_1_a_triskelavite_flying_ammo.txt b/forge-gui/res/tokenscripts/c_1_1_a_triskelavite_flying_ammo.txt index c8af904ab6b..8aed33b9532 100644 --- a/forge-gui/res/tokenscripts/c_1_1_a_triskelavite_flying_ammo.txt +++ b/forge-gui/res/tokenscripts/c_1_1_a_triskelavite_flying_ammo.txt @@ -1,4 +1,4 @@ -Name:Triskelavite +Name:Triskelavite Token ManaCost:no cost Types:Artifact Creature Triskelavite K:Flying diff --git a/forge-gui/res/tokenscripts/c_1_1_eldrazi_scion_sac.txt b/forge-gui/res/tokenscripts/c_1_1_eldrazi_scion_sac.txt index 3cabab4de1b..f7e61a3f3a7 100644 --- a/forge-gui/res/tokenscripts/c_1_1_eldrazi_scion_sac.txt +++ b/forge-gui/res/tokenscripts/c_1_1_eldrazi_scion_sac.txt @@ -1,4 +1,4 @@ -Name:Eldrazi Scion +Name:Eldrazi Scion Token ManaCost:no cost PT:1/1 Types:Creature Eldrazi Scion diff --git a/forge-gui/res/tokenscripts/c_1_1_eldrazi_sliver_sac.txt b/forge-gui/res/tokenscripts/c_1_1_eldrazi_sliver_sac.txt index 6612bd357b9..133f11299c7 100644 --- a/forge-gui/res/tokenscripts/c_1_1_eldrazi_sliver_sac.txt +++ b/forge-gui/res/tokenscripts/c_1_1_eldrazi_sliver_sac.txt @@ -1,4 +1,4 @@ -Name:Eldrazi Sliver +Name:Eldrazi Sliver Token ManaCost:no cost PT:1/1 Types:Creature Eldrazi Sliver diff --git a/forge-gui/res/tokenscripts/c_1_1_sand.txt b/forge-gui/res/tokenscripts/c_1_1_sand.txt index d07cdf24e93..90745ace04a 100644 --- a/forge-gui/res/tokenscripts/c_1_1_sand.txt +++ b/forge-gui/res/tokenscripts/c_1_1_sand.txt @@ -1,4 +1,4 @@ -Name:Sand +Name:Sand Token ManaCost:no cost Types:Creature Sand PT:1/1 diff --git a/forge-gui/res/tokenscripts/c_1_1_shapeshifter_changeling.txt b/forge-gui/res/tokenscripts/c_1_1_shapeshifter_changeling.txt index 590e005e5bd..f3a59799e2b 100644 --- a/forge-gui/res/tokenscripts/c_1_1_shapeshifter_changeling.txt +++ b/forge-gui/res/tokenscripts/c_1_1_shapeshifter_changeling.txt @@ -1,4 +1,4 @@ -Name:Shapeshifter +Name:Shapeshifter Token ManaCost:no cost Types:Creature Shapeshifter PT:1/1 diff --git a/forge-gui/res/tokenscripts/c_1_1_sliver.txt b/forge-gui/res/tokenscripts/c_1_1_sliver.txt index 3de9b501bd5..da1c458fec9 100644 --- a/forge-gui/res/tokenscripts/c_1_1_sliver.txt +++ b/forge-gui/res/tokenscripts/c_1_1_sliver.txt @@ -1,4 +1,4 @@ -Name:Sliver +Name:Sliver Token ManaCost:no cost Types:Creature Sliver PT:1/1 diff --git a/forge-gui/res/tokenscripts/c_1_1_spirit.txt b/forge-gui/res/tokenscripts/c_1_1_spirit.txt index ac5d339f65d..e1464633bc5 100644 --- a/forge-gui/res/tokenscripts/c_1_1_spirit.txt +++ b/forge-gui/res/tokenscripts/c_1_1_spirit.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Creature Spirit PT:1/1 diff --git a/forge-gui/res/tokenscripts/c_1_1_spirit_lifelink_haste.txt b/forge-gui/res/tokenscripts/c_1_1_spirit_lifelink_haste.txt index b8b2f9702fc..341f15be1b5 100644 --- a/forge-gui/res/tokenscripts/c_1_1_spirit_lifelink_haste.txt +++ b/forge-gui/res/tokenscripts/c_1_1_spirit_lifelink_haste.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Creature Spirit PT:1/1 diff --git a/forge-gui/res/tokenscripts/c_2_2_a_assembly_worker.txt b/forge-gui/res/tokenscripts/c_2_2_a_assembly_worker.txt index 5d597a14940..c2f2a773446 100644 --- a/forge-gui/res/tokenscripts/c_2_2_a_assembly_worker.txt +++ b/forge-gui/res/tokenscripts/c_2_2_a_assembly_worker.txt @@ -1,4 +1,4 @@ -Name:Assembly-Worker +Name:Assembly-Worker Token ManaCost:no cost PT:2/2 Types:Artifact Creature Assembly-Worker diff --git a/forge-gui/res/tokenscripts/c_2_2_a_spawn.txt b/forge-gui/res/tokenscripts/c_2_2_a_spawn.txt index ca02fe591c1..23e006e58f4 100644 --- a/forge-gui/res/tokenscripts/c_2_2_a_spawn.txt +++ b/forge-gui/res/tokenscripts/c_2_2_a_spawn.txt @@ -1,4 +1,4 @@ -Name:Spawn +Name:Spawn Token ManaCost:no cost PT:2/2 Types:Artifact Creature Spawn diff --git a/forge-gui/res/tokenscripts/c_2_2_homunculus.txt b/forge-gui/res/tokenscripts/c_2_2_homunculus.txt index 3063ef6392e..16676921c2e 100644 --- a/forge-gui/res/tokenscripts/c_2_2_homunculus.txt +++ b/forge-gui/res/tokenscripts/c_2_2_homunculus.txt @@ -1,4 +1,4 @@ -Name:Homunculus +Name:Homunculus Token ManaCost:no cost PT:2/2 Types:Creature Homunculus diff --git a/forge-gui/res/tokenscripts/c_2_2_pincher.txt b/forge-gui/res/tokenscripts/c_2_2_pincher.txt index f1de257fb22..775be92b39e 100644 --- a/forge-gui/res/tokenscripts/c_2_2_pincher.txt +++ b/forge-gui/res/tokenscripts/c_2_2_pincher.txt @@ -1,4 +1,4 @@ -Name:Pincher +Name:Pincher Token ManaCost:no cost PT:2/2 Types:Creature Pincher diff --git a/forge-gui/res/tokenscripts/c_2_2_shapeshifter_changeling.txt b/forge-gui/res/tokenscripts/c_2_2_shapeshifter_changeling.txt index 50a661a2063..a43bbc1ad9b 100644 --- a/forge-gui/res/tokenscripts/c_2_2_shapeshifter_changeling.txt +++ b/forge-gui/res/tokenscripts/c_2_2_shapeshifter_changeling.txt @@ -1,4 +1,4 @@ -Name:Shapeshifter +Name:Shapeshifter Token ManaCost:no cost Types:Creature Shapeshifter PT:2/2 diff --git a/forge-gui/res/tokenscripts/c_2_2_spirit.txt b/forge-gui/res/tokenscripts/c_2_2_spirit.txt index fd30bfb4ca7..c6c6e3e68b3 100644 --- a/forge-gui/res/tokenscripts/c_2_2_spirit.txt +++ b/forge-gui/res/tokenscripts/c_2_2_spirit.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Creature Spirit PT:2/2 diff --git a/forge-gui/res/tokenscripts/c_3_2_eldrazi_horror.txt b/forge-gui/res/tokenscripts/c_3_2_eldrazi_horror.txt index c8afcdf8d11..aac7ffe0789 100644 --- a/forge-gui/res/tokenscripts/c_3_2_eldrazi_horror.txt +++ b/forge-gui/res/tokenscripts/c_3_2_eldrazi_horror.txt @@ -1,4 +1,4 @@ -Name:Eldrazi Horror +Name:Eldrazi Horror Token ManaCost:no cost PT:3/2 Types:Creature Eldrazi Horror diff --git a/forge-gui/res/tokenscripts/c_3_3_a_golem.txt b/forge-gui/res/tokenscripts/c_3_3_a_golem.txt index 1fe78bf886a..401e57735ed 100644 --- a/forge-gui/res/tokenscripts/c_3_3_a_golem.txt +++ b/forge-gui/res/tokenscripts/c_3_3_a_golem.txt @@ -1,4 +1,4 @@ -Name:Golem +Name:Golem Token ManaCost:no cost PT:3/3 Types:Artifact Creature Golem diff --git a/forge-gui/res/tokenscripts/c_3_3_a_golem_flying.txt b/forge-gui/res/tokenscripts/c_3_3_a_golem_flying.txt index d3516ace82d..ae0db67ffc9 100644 --- a/forge-gui/res/tokenscripts/c_3_3_a_golem_flying.txt +++ b/forge-gui/res/tokenscripts/c_3_3_a_golem_flying.txt @@ -1,4 +1,4 @@ -Name:Golem +Name:Golem Token ManaCost:no cost PT:3/3 Types:Artifact Creature Golem diff --git a/forge-gui/res/tokenscripts/c_3_3_a_golem_trample.txt b/forge-gui/res/tokenscripts/c_3_3_a_golem_trample.txt index 6923facfbea..61d30171dfc 100644 --- a/forge-gui/res/tokenscripts/c_3_3_a_golem_trample.txt +++ b/forge-gui/res/tokenscripts/c_3_3_a_golem_trample.txt @@ -1,4 +1,4 @@ -Name:Golem +Name:Golem Token ManaCost:no cost PT:3/3 Types:Artifact Creature Golem diff --git a/forge-gui/res/tokenscripts/c_3_3_a_golem_vigilance.txt b/forge-gui/res/tokenscripts/c_3_3_a_golem_vigilance.txt index 40fd9c7deac..361beb289cf 100644 --- a/forge-gui/res/tokenscripts/c_3_3_a_golem_vigilance.txt +++ b/forge-gui/res/tokenscripts/c_3_3_a_golem_vigilance.txt @@ -1,4 +1,4 @@ -Name:Golem +Name:Golem Token ManaCost:no cost PT:3/3 Types:Artifact Creature Golem diff --git a/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_golem.txt b/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_golem.txt index 56d4d7d3284..e61c845aa4d 100644 --- a/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_golem.txt +++ b/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_golem.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Golem +Name:Phyrexian Golem Token ManaCost:no cost PT:3/3 Types:Artifact Creature Phyrexian Golem diff --git a/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_wurm_deathtouch.txt b/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_wurm_deathtouch.txt index 02b8a2312b9..1319391a7d5 100644 --- a/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_wurm_deathtouch.txt +++ b/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_wurm_deathtouch.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Wurm +Name:Phyrexian Wurm Token ManaCost:no cost Types:Artifact Creature Phyrexian Wurm PT:3/3 diff --git a/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_wurm_lifelink.txt b/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_wurm_lifelink.txt index e342b4ab46d..c9cbdfe7692 100644 --- a/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_wurm_lifelink.txt +++ b/forge-gui/res/tokenscripts/c_3_3_a_phyrexian_wurm_lifelink.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Wurm +Name:Phyrexian Wurm Token ManaCost:no cost Types:Artifact Creature Phyrexian Wurm PT:3/3 diff --git a/forge-gui/res/tokenscripts/c_3_3_e_a_golem.txt b/forge-gui/res/tokenscripts/c_3_3_e_a_golem.txt index a65680df009..b45c2573eb9 100644 --- a/forge-gui/res/tokenscripts/c_3_3_e_a_golem.txt +++ b/forge-gui/res/tokenscripts/c_3_3_e_a_golem.txt @@ -1,4 +1,4 @@ -Name:Golem +Name:Golem Token ManaCost:no cost PT:3/3 Types:Enchantment Artifact Creature Golem diff --git a/forge-gui/res/tokenscripts/c_3_4_a_gargoyle_flying.txt b/forge-gui/res/tokenscripts/c_3_4_a_gargoyle_flying.txt index 154c7128df8..3b503259960 100644 --- a/forge-gui/res/tokenscripts/c_3_4_a_gargoyle_flying.txt +++ b/forge-gui/res/tokenscripts/c_3_4_a_gargoyle_flying.txt @@ -1,4 +1,4 @@ -Name:Gargoyle +Name:Gargoyle Token Types:Artifact Creature Gargoyle ManaCost:no cost K:Flying diff --git a/forge-gui/res/tokenscripts/c_4_4_a_construct.txt b/forge-gui/res/tokenscripts/c_4_4_a_construct.txt index 45957ca6286..37e1729344c 100644 --- a/forge-gui/res/tokenscripts/c_4_4_a_construct.txt +++ b/forge-gui/res/tokenscripts/c_4_4_a_construct.txt @@ -1,4 +1,4 @@ -Name:Construct +Name:Construct Token ManaCost:no cost PT:4/4 Types:Artifact Creature Construct diff --git a/forge-gui/res/tokenscripts/c_4_4_a_golem.txt b/forge-gui/res/tokenscripts/c_4_4_a_golem.txt index a68532d5999..e6b004a7787 100644 --- a/forge-gui/res/tokenscripts/c_4_4_a_golem.txt +++ b/forge-gui/res/tokenscripts/c_4_4_a_golem.txt @@ -1,4 +1,4 @@ -Name:Golem +Name:Golem Token ManaCost:no cost PT:4/4 Types:Artifact Creature Golem diff --git a/forge-gui/res/tokenscripts/c_4_4_dragon_flying.txt b/forge-gui/res/tokenscripts/c_4_4_dragon_flying.txt index d9086aa06cc..ed1f0fec137 100644 --- a/forge-gui/res/tokenscripts/c_4_4_dragon_flying.txt +++ b/forge-gui/res/tokenscripts/c_4_4_dragon_flying.txt @@ -1,4 +1,4 @@ -Name:Dragon +Name:Dragon Token ManaCost:no cost Types:Creature Dragon K:Flying diff --git a/forge-gui/res/tokenscripts/c_4_6_a_golem.txt b/forge-gui/res/tokenscripts/c_4_6_a_golem.txt index ac301687f4f..38a0cd2457f 100644 --- a/forge-gui/res/tokenscripts/c_4_6_a_golem.txt +++ b/forge-gui/res/tokenscripts/c_4_6_a_golem.txt @@ -1,4 +1,4 @@ -Name:Golem +Name:Golem Token ManaCost:no cost PT:4/6 Types:Artifact Creature Golem diff --git a/forge-gui/res/tokenscripts/c_5_5_a_djinn_flying.txt b/forge-gui/res/tokenscripts/c_5_5_a_djinn_flying.txt index aeeedcd70f2..82033f978e9 100644 --- a/forge-gui/res/tokenscripts/c_5_5_a_djinn_flying.txt +++ b/forge-gui/res/tokenscripts/c_5_5_a_djinn_flying.txt @@ -1,4 +1,4 @@ -Name:Djinn +Name:Djinn Token Types:Artifact Creature Djinn ManaCost:no cost K:Flying diff --git a/forge-gui/res/tokenscripts/c_6_12_a_construct_trample.txt b/forge-gui/res/tokenscripts/c_6_12_a_construct_trample.txt index 05979e73c36..6a65dd5dfc2 100644 --- a/forge-gui/res/tokenscripts/c_6_12_a_construct_trample.txt +++ b/forge-gui/res/tokenscripts/c_6_12_a_construct_trample.txt @@ -1,4 +1,4 @@ -Name:Construct +Name:Construct Token ManaCost:no cost Types:Artifact Creature Construct K:Trample diff --git a/forge-gui/res/tokenscripts/c_6_6_a_beast.txt b/forge-gui/res/tokenscripts/c_6_6_a_beast.txt index ff1b22f39ef..6481fb594d5 100644 --- a/forge-gui/res/tokenscripts/c_6_6_a_beast.txt +++ b/forge-gui/res/tokenscripts/c_6_6_a_beast.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token ManaCost:no cost PT:6/6 Types:Artifact Creature Beast diff --git a/forge-gui/res/tokenscripts/c_7_7_eldrazi_annihilator.txt b/forge-gui/res/tokenscripts/c_7_7_eldrazi_annihilator.txt index a6929cd6e73..29143629d0d 100644 --- a/forge-gui/res/tokenscripts/c_7_7_eldrazi_annihilator.txt +++ b/forge-gui/res/tokenscripts/c_7_7_eldrazi_annihilator.txt @@ -1,4 +1,4 @@ -Name:Eldrazi +Name:Eldrazi Token ManaCost:no cost Types:Creature Eldrazi PT:7/7 diff --git a/forge-gui/res/tokenscripts/c_9_9_a_golem.txt b/forge-gui/res/tokenscripts/c_9_9_a_golem.txt index 40d0cb68d4d..fdd27bf3484 100644 --- a/forge-gui/res/tokenscripts/c_9_9_a_golem.txt +++ b/forge-gui/res/tokenscripts/c_9_9_a_golem.txt @@ -1,4 +1,4 @@ -Name:Golem +Name:Golem Token ManaCost:no cost PT:9/9 Types:Artifact Creature Golem diff --git a/forge-gui/res/tokenscripts/c_a_blood_draw.txt b/forge-gui/res/tokenscripts/c_a_blood_draw.txt index c16816c0b0a..e7746ffd675 100644 --- a/forge-gui/res/tokenscripts/c_a_blood_draw.txt +++ b/forge-gui/res/tokenscripts/c_a_blood_draw.txt @@ -1,4 +1,4 @@ -Name:Blood +Name:Blood Token ManaCost:no cost Types:Artifact Blood A:AB$ Draw | Cost$ 1 T Discard<1/Card> Sac<1/CARDNAME/this artifact> | NumCards$ 1 | SpellDescription$ Draw a card. diff --git a/forge-gui/res/tokenscripts/c_a_clue_draw.txt b/forge-gui/res/tokenscripts/c_a_clue_draw.txt index d03be3a67aa..f5684e7da3c 100644 --- a/forge-gui/res/tokenscripts/c_a_clue_draw.txt +++ b/forge-gui/res/tokenscripts/c_a_clue_draw.txt @@ -1,4 +1,4 @@ -Name:Clue +Name:Clue Token ManaCost:no cost Types:Artifact Clue A:AB$ Draw | Cost$ 2 Sac<1/CARDNAME/this artifact> | NumCards$ 1 | SpellDescription$ Draw a card. diff --git a/forge-gui/res/tokenscripts/c_a_food_sac.txt b/forge-gui/res/tokenscripts/c_a_food_sac.txt index 7d14f0658a2..78b90b13f14 100644 --- a/forge-gui/res/tokenscripts/c_a_food_sac.txt +++ b/forge-gui/res/tokenscripts/c_a_food_sac.txt @@ -1,4 +1,4 @@ -Name:Food +Name:Food Token ManaCost:no cost Types:Artifact Food A:AB$ GainLife | Cost$ 2 T Sac<1/CARDNAME> | Defined$ You | LifeAmount$ 3 | SpellDescription$ You gain 3 life. diff --git a/forge-gui/res/tokenscripts/gold.txt b/forge-gui/res/tokenscripts/c_a_gold_draw.txt similarity index 92% rename from forge-gui/res/tokenscripts/gold.txt rename to forge-gui/res/tokenscripts/c_a_gold_draw.txt index 5372d284c2b..973cd884491 100644 --- a/forge-gui/res/tokenscripts/gold.txt +++ b/forge-gui/res/tokenscripts/c_a_gold_draw.txt @@ -1,4 +1,4 @@ -Name:Gold +Name:Gold Token ManaCost:no cost Types:Artifact Gold A:AB$ Mana | Cost$ Sac<1/CARDNAME> | Produced$ Any | SpellDescription$ Add one mana of any color. diff --git a/forge-gui/res/tokenscripts/c_a_treasure_sac.txt b/forge-gui/res/tokenscripts/c_a_treasure_sac.txt index 1f2075e0d6b..2a52fdf918f 100644 --- a/forge-gui/res/tokenscripts/c_a_treasure_sac.txt +++ b/forge-gui/res/tokenscripts/c_a_treasure_sac.txt @@ -1,4 +1,4 @@ -Name:Treasure +Name:Treasure Token ManaCost:no cost Types:Artifact Treasure A:AB$ Mana | Cost$ T Sac<1/CARDNAME> | Produced$ Any | Amount$ 1 | SpellDescription$ Add one mana of any color. diff --git a/forge-gui/res/tokenscripts/shard.txt b/forge-gui/res/tokenscripts/c_e_shard_draw.txt similarity index 89% rename from forge-gui/res/tokenscripts/shard.txt rename to forge-gui/res/tokenscripts/c_e_shard_draw.txt index 14e9f257369..b7fb6baf705 100644 --- a/forge-gui/res/tokenscripts/shard.txt +++ b/forge-gui/res/tokenscripts/c_e_shard_draw.txt @@ -1,6 +1,6 @@ -Name:Shard +Name:Shard Token ManaCost:no cost -Types:Enchantment +Types:Enchantment Shard A:AB$ Scry | Cost$ 2 Sac<1/CARDNAME> | CostDesc$ {2}, Sacrifice this enchantment: | ScryNum$ 1 | SubAbility$ DBDraw | StackDescription$ SpellDescription | SpellDescription$ Scry 1, then draw a card. SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1 | StackDescription$ None Oracle:{2}, Sacrifice this enchantment: Scry 1, then draw a card. diff --git a/forge-gui/res/tokenscripts/c_l_forest.txt b/forge-gui/res/tokenscripts/c_l_forest.txt index 349319bc251..deebb5ef659 100644 --- a/forge-gui/res/tokenscripts/c_l_forest.txt +++ b/forge-gui/res/tokenscripts/c_l_forest.txt @@ -1,4 +1,4 @@ -Name:Forest +Name:Forest Token ManaCost:no cost Types:Land Forest Oracle: diff --git a/forge-gui/res/tokenscripts/c_l_wastes.txt b/forge-gui/res/tokenscripts/c_l_wastes.txt index 029f6aa87a8..476a030e1ed 100644 --- a/forge-gui/res/tokenscripts/c_l_wastes.txt +++ b/forge-gui/res/tokenscripts/c_l_wastes.txt @@ -1,4 +1,4 @@ -Name:Wastes +Name:Wastes Token ManaCost:no cost Types:Land A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. diff --git a/forge-gui/res/tokenscripts/c_x_x_a_construct.txt b/forge-gui/res/tokenscripts/c_x_x_a_construct.txt index f835d63268a..432475d83d0 100644 --- a/forge-gui/res/tokenscripts/c_x_x_a_construct.txt +++ b/forge-gui/res/tokenscripts/c_x_x_a_construct.txt @@ -1,4 +1,4 @@ -Name:Construct +Name:Construct Token ManaCost:no cost Types:Artifact Creature Construct PT:*/* diff --git a/forge-gui/res/tokenscripts/c_x_x_a_horror.txt b/forge-gui/res/tokenscripts/c_x_x_a_horror.txt index 8165330fef8..89442b94c11 100644 --- a/forge-gui/res/tokenscripts/c_x_x_a_horror.txt +++ b/forge-gui/res/tokenscripts/c_x_x_a_horror.txt @@ -1,4 +1,4 @@ -Name:Horror +Name:Horror Token ManaCost:no cost Types:Artifact Creature Horror PT:*/* diff --git a/forge-gui/res/tokenscripts/c_x_x_a_phyrexian_horror.txt b/forge-gui/res/tokenscripts/c_x_x_a_phyrexian_horror.txt index 05fe38ac950..eef952fa629 100644 --- a/forge-gui/res/tokenscripts/c_x_x_a_phyrexian_horror.txt +++ b/forge-gui/res/tokenscripts/c_x_x_a_phyrexian_horror.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Horror +Name:Phyrexian Horror Token ManaCost:no cost Types:Artifact Creature Phyrexian Horror PT:*/* diff --git a/forge-gui/res/tokenscripts/c_x_x_a_sculpture_total_sculptures.txt b/forge-gui/res/tokenscripts/c_x_x_a_sculpture_total_sculptures.txt index bd1a66f7714..8a95ab01113 100644 --- a/forge-gui/res/tokenscripts/c_x_x_a_sculpture_total_sculptures.txt +++ b/forge-gui/res/tokenscripts/c_x_x_a_sculpture_total_sculptures.txt @@ -1,4 +1,4 @@ -Name:Sculpture +Name:Sculpture Token ManaCost:no cost Types:Artifact Creature Sculpture PT:*/* diff --git a/forge-gui/res/tokenscripts/g_0_0_hydra.txt b/forge-gui/res/tokenscripts/g_0_0_hydra.txt index c03d10e6148..4f17f4ca85d 100644 --- a/forge-gui/res/tokenscripts/g_0_0_hydra.txt +++ b/forge-gui/res/tokenscripts/g_0_0_hydra.txt @@ -1,4 +1,4 @@ -Name:Hydra +Name:Hydra Token Colors:green ManaCost:no cost PT:0/0 diff --git a/forge-gui/res/tokenscripts/g_0_1_egg_defender.txt b/forge-gui/res/tokenscripts/g_0_1_egg_defender.txt index bb183060660..40163bfca0c 100644 --- a/forge-gui/res/tokenscripts/g_0_1_egg_defender.txt +++ b/forge-gui/res/tokenscripts/g_0_1_egg_defender.txt @@ -1,4 +1,4 @@ -Name:Egg +Name:Egg Token ManaCost:no cost Types:Creature Egg Colors:green diff --git a/forge-gui/res/tokenscripts/g_0_1_plant.txt b/forge-gui/res/tokenscripts/g_0_1_plant.txt index 76c1b8f7958..10e5b900179 100644 --- a/forge-gui/res/tokenscripts/g_0_1_plant.txt +++ b/forge-gui/res/tokenscripts/g_0_1_plant.txt @@ -1,4 +1,4 @@ -Name:Plant +Name:Plant Token ManaCost:no cost Types:Creature Plant Colors:green diff --git a/forge-gui/res/tokenscripts/g_0_1_sheep.txt b/forge-gui/res/tokenscripts/g_0_1_sheep.txt index 776cb9f4060..2d1213c9f9f 100644 --- a/forge-gui/res/tokenscripts/g_0_1_sheep.txt +++ b/forge-gui/res/tokenscripts/g_0_1_sheep.txt @@ -1,4 +1,4 @@ -Name:Sheep +Name:Sheep Token ManaCost:no cost PT:0/1 Colors:green diff --git a/forge-gui/res/tokenscripts/g_0_2_plant_defender.txt b/forge-gui/res/tokenscripts/g_0_2_plant_defender.txt index 38d413ff228..f491f922e24 100644 --- a/forge-gui/res/tokenscripts/g_0_2_plant_defender.txt +++ b/forge-gui/res/tokenscripts/g_0_2_plant_defender.txt @@ -1,4 +1,4 @@ -Name:Plant +Name:Plant Token ManaCost:no cost Types:Creature Plant Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_ape.txt b/forge-gui/res/tokenscripts/g_1_1_ape.txt index 32ea00cac30..673981862e5 100644 --- a/forge-gui/res/tokenscripts/g_1_1_ape.txt +++ b/forge-gui/res/tokenscripts/g_1_1_ape.txt @@ -1,4 +1,4 @@ -Name:Ape +Name:Ape Token ManaCost:no cost Types:Creature Ape Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_boar_food.txt b/forge-gui/res/tokenscripts/g_1_1_boar_food.txt index d04e54bb41d..977bf719441 100644 --- a/forge-gui/res/tokenscripts/g_1_1_boar_food.txt +++ b/forge-gui/res/tokenscripts/g_1_1_boar_food.txt @@ -1,4 +1,4 @@ -Name:Boar +Name:Boar Token ManaCost:no cost Types:Creature Boar Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_cat.txt b/forge-gui/res/tokenscripts/g_1_1_cat.txt index 8195fccb46c..2a4c87d1158 100644 --- a/forge-gui/res/tokenscripts/g_1_1_cat.txt +++ b/forge-gui/res/tokenscripts/g_1_1_cat.txt @@ -1,4 +1,4 @@ -Name:Cat +Name:Cat Token ManaCost:no cost Types:Creature Cat Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_dog.txt b/forge-gui/res/tokenscripts/g_1_1_dog.txt index 9ea3f849c18..e033a3fe7c8 100644 --- a/forge-gui/res/tokenscripts/g_1_1_dog.txt +++ b/forge-gui/res/tokenscripts/g_1_1_dog.txt @@ -1,4 +1,4 @@ -Name:Dog +Name:Dog Token ManaCost:no cost PT:1/1 Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_elf_druid_g.txt b/forge-gui/res/tokenscripts/g_1_1_elf_druid_g.txt index ccadf3197bb..1866507c108 100644 --- a/forge-gui/res/tokenscripts/g_1_1_elf_druid_g.txt +++ b/forge-gui/res/tokenscripts/g_1_1_elf_druid_g.txt @@ -1,4 +1,4 @@ -Name:Elf Druid +Name:Elf Druid Token ManaCost:no cost Types:Creature Elf Druid Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_elf_g.txt b/forge-gui/res/tokenscripts/g_1_1_elf_g.txt index fe448b17ae8..ce33e030e5b 100644 --- a/forge-gui/res/tokenscripts/g_1_1_elf_g.txt +++ b/forge-gui/res/tokenscripts/g_1_1_elf_g.txt @@ -1,4 +1,4 @@ -Name:Elf +Name:Elf Token ManaCost:no cost Types:Creature Elf Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_elf_warrior.txt b/forge-gui/res/tokenscripts/g_1_1_elf_warrior.txt index 44eb53e1554..24a56c12b94 100644 --- a/forge-gui/res/tokenscripts/g_1_1_elf_warrior.txt +++ b/forge-gui/res/tokenscripts/g_1_1_elf_warrior.txt @@ -1,4 +1,4 @@ -Name:Elf Warrior +Name:Elf Warrior Token ManaCost:no cost Types:Creature Elf Warrior Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_hippo.txt b/forge-gui/res/tokenscripts/g_1_1_hippo.txt index 8031a516872..794d0712d26 100644 --- a/forge-gui/res/tokenscripts/g_1_1_hippo.txt +++ b/forge-gui/res/tokenscripts/g_1_1_hippo.txt @@ -1,4 +1,4 @@ -Name:Hippo +Name:Hippo Token ManaCost:no cost Types:Creature Hippo Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_insect.txt b/forge-gui/res/tokenscripts/g_1_1_insect.txt index 37b284194de..1a1cbf68a3c 100644 --- a/forge-gui/res/tokenscripts/g_1_1_insect.txt +++ b/forge-gui/res/tokenscripts/g_1_1_insect.txt @@ -1,4 +1,4 @@ -Name:Insect +Name:Insect Token ManaCost:no cost PT:1/1 Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_insect_flying_deathtouch.txt b/forge-gui/res/tokenscripts/g_1_1_insect_flying_deathtouch.txt index 072ef81c2c2..a6448a305e6 100644 --- a/forge-gui/res/tokenscripts/g_1_1_insect_flying_deathtouch.txt +++ b/forge-gui/res/tokenscripts/g_1_1_insect_flying_deathtouch.txt @@ -1,4 +1,4 @@ -Name:Insect +Name:Insect Token ManaCost:no cost PT:1/1 Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_ooze.txt b/forge-gui/res/tokenscripts/g_1_1_ooze.txt index 86dc06b7011..95a68b9c8a3 100644 --- a/forge-gui/res/tokenscripts/g_1_1_ooze.txt +++ b/forge-gui/res/tokenscripts/g_1_1_ooze.txt @@ -1,4 +1,4 @@ -Name:Ooze +Name:Ooze Token ManaCost:no cost Types:Creature Ooze Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_phyrexian_insect_infect.txt b/forge-gui/res/tokenscripts/g_1_1_phyrexian_insect_infect.txt index 79c5789030d..c7b2e2ac5f8 100644 --- a/forge-gui/res/tokenscripts/g_1_1_phyrexian_insect_infect.txt +++ b/forge-gui/res/tokenscripts/g_1_1_phyrexian_insect_infect.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Insect +Name:Phyrexian Insect Token ManaCost:no cost PT:1/1 Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_plant.txt b/forge-gui/res/tokenscripts/g_1_1_plant.txt index 3fdb50d64a8..39b141dd1e1 100644 --- a/forge-gui/res/tokenscripts/g_1_1_plant.txt +++ b/forge-gui/res/tokenscripts/g_1_1_plant.txt @@ -1,4 +1,4 @@ -Name:Plant +Name:Plant Token ManaCost:no cost Types:Creature Plant Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_saproling.txt b/forge-gui/res/tokenscripts/g_1_1_saproling.txt index ce69a8adaf8..2c0cc5355e1 100644 --- a/forge-gui/res/tokenscripts/g_1_1_saproling.txt +++ b/forge-gui/res/tokenscripts/g_1_1_saproling.txt @@ -1,4 +1,4 @@ -Name:Saproling +Name:Saproling Token ManaCost:no cost Types:Creature Saproling Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_snake.txt b/forge-gui/res/tokenscripts/g_1_1_snake.txt index 6f458cd6e69..85efd1a2606 100644 --- a/forge-gui/res/tokenscripts/g_1_1_snake.txt +++ b/forge-gui/res/tokenscripts/g_1_1_snake.txt @@ -1,4 +1,4 @@ -Name:Snake +Name:Snake Token ManaCost:no cost Types:Creature Snake Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_snake_deathtouch.txt b/forge-gui/res/tokenscripts/g_1_1_snake_deathtouch.txt index 3775bb39690..e743a77c835 100644 --- a/forge-gui/res/tokenscripts/g_1_1_snake_deathtouch.txt +++ b/forge-gui/res/tokenscripts/g_1_1_snake_deathtouch.txt @@ -1,4 +1,4 @@ -Name:Snake +Name:Snake Token ManaCost:no cost Types:Creature Snake Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_spike.txt b/forge-gui/res/tokenscripts/g_1_1_spike.txt index aeea0d52da5..8a8e4363f8c 100644 --- a/forge-gui/res/tokenscripts/g_1_1_spike.txt +++ b/forge-gui/res/tokenscripts/g_1_1_spike.txt @@ -1,4 +1,4 @@ -Name:Spike +Name:Spike Token ManaCost:no cost Types:Creature Spike Colors:green diff --git a/forge-gui/res/tokenscripts/g_1_1_splinter_flying_cum.txt b/forge-gui/res/tokenscripts/g_1_1_splinter_flying_cum.txt index 0a7aa8f5550..c8bf01a4df8 100644 --- a/forge-gui/res/tokenscripts/g_1_1_splinter_flying_cum.txt +++ b/forge-gui/res/tokenscripts/g_1_1_splinter_flying_cum.txt @@ -1,4 +1,4 @@ -Name:Splinter +Name:Splinter Token ManaCost:no cost Colors:green Types:Creature Splinter diff --git a/forge-gui/res/tokenscripts/g_1_1_squirrel.txt b/forge-gui/res/tokenscripts/g_1_1_squirrel.txt index 1653b87b7c6..b7bf449538b 100644 --- a/forge-gui/res/tokenscripts/g_1_1_squirrel.txt +++ b/forge-gui/res/tokenscripts/g_1_1_squirrel.txt @@ -1,4 +1,4 @@ -Name:Squirrel +Name:Squirrel Token ManaCost:no cost Types:Creature Squirrel PT:1/1 diff --git a/forge-gui/res/tokenscripts/g_1_1_wolf_sound_the_call.txt b/forge-gui/res/tokenscripts/g_1_1_wolf_sound_the_call.txt index bb9d7600b1d..d802a702bbe 100644 --- a/forge-gui/res/tokenscripts/g_1_1_wolf_sound_the_call.txt +++ b/forge-gui/res/tokenscripts/g_1_1_wolf_sound_the_call.txt @@ -1,4 +1,4 @@ -Name:Wolf +Name:Wolf Token ManaCost:no cost Colors:green Types:Creature Wolf diff --git a/forge-gui/res/tokenscripts/g_1_2_spider_reach.txt b/forge-gui/res/tokenscripts/g_1_2_spider_reach.txt index d6e16a39af3..2f6b0594990 100644 --- a/forge-gui/res/tokenscripts/g_1_2_spider_reach.txt +++ b/forge-gui/res/tokenscripts/g_1_2_spider_reach.txt @@ -1,4 +1,4 @@ -Name:Spider +Name:Spider Token ManaCost:no cost Types:Creature Spider PT:1/2 diff --git a/forge-gui/res/tokenscripts/g_1_3_e_spider_reach.txt b/forge-gui/res/tokenscripts/g_1_3_e_spider_reach.txt index 7cc74c232fa..ad0d5dda10e 100644 --- a/forge-gui/res/tokenscripts/g_1_3_e_spider_reach.txt +++ b/forge-gui/res/tokenscripts/g_1_3_e_spider_reach.txt @@ -1,4 +1,4 @@ -Name:Spider +Name:Spider Token ManaCost:no cost Types:Enchantment Creature Spider PT:1/3 diff --git a/forge-gui/res/tokenscripts/g_2_2_bear.txt b/forge-gui/res/tokenscripts/g_2_2_bear.txt index 2b1cead38f8..646229eb283 100644 --- a/forge-gui/res/tokenscripts/g_2_2_bear.txt +++ b/forge-gui/res/tokenscripts/g_2_2_bear.txt @@ -1,4 +1,4 @@ -Name:Bear +Name:Bear Token ManaCost:no cost PT:2/2 Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_beast.txt b/forge-gui/res/tokenscripts/g_2_2_beast.txt index 78c4f2e3611..07f17063880 100644 --- a/forge-gui/res/tokenscripts/g_2_2_beast.txt +++ b/forge-gui/res/tokenscripts/g_2_2_beast.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token ManaCost:no cost PT:2/2 Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_boar.txt b/forge-gui/res/tokenscripts/g_2_2_boar.txt index ea3e25d0771..7beac13f444 100644 --- a/forge-gui/res/tokenscripts/g_2_2_boar.txt +++ b/forge-gui/res/tokenscripts/g_2_2_boar.txt @@ -1,4 +1,4 @@ -Name:Boar +Name:Boar Token ManaCost:no cost PT:2/2 Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_cat.txt b/forge-gui/res/tokenscripts/g_2_2_cat.txt index c8cfa06710c..d3d0ecac21a 100644 --- a/forge-gui/res/tokenscripts/g_2_2_cat.txt +++ b/forge-gui/res/tokenscripts/g_2_2_cat.txt @@ -1,4 +1,4 @@ -Name:Cat +Name:Cat Token Colors:green ManaCost:no cost PT:2/2 diff --git a/forge-gui/res/tokenscripts/g_2_2_cat_warrior_forestwalk.txt b/forge-gui/res/tokenscripts/g_2_2_cat_warrior_forestwalk.txt index 9db0d4debe9..9bdf73f4b49 100644 --- a/forge-gui/res/tokenscripts/g_2_2_cat_warrior_forestwalk.txt +++ b/forge-gui/res/tokenscripts/g_2_2_cat_warrior_forestwalk.txt @@ -1,4 +1,4 @@ -Name:Cat Warrior +Name:Cat Warrior Token ManaCost:no cost Types:Creature Cat Warrior Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_elemental.txt b/forge-gui/res/tokenscripts/g_2_2_elemental.txt index 565a4bdd7c6..eaf60c03abb 100644 --- a/forge-gui/res/tokenscripts/g_2_2_elemental.txt +++ b/forge-gui/res/tokenscripts/g_2_2_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token Colors:green ManaCost:no cost PT:2/2 diff --git a/forge-gui/res/tokenscripts/g_2_2_gorilla.txt b/forge-gui/res/tokenscripts/g_2_2_gorilla.txt index 3094eaff857..16e765f86f4 100644 --- a/forge-gui/res/tokenscripts/g_2_2_gorilla.txt +++ b/forge-gui/res/tokenscripts/g_2_2_gorilla.txt @@ -1,4 +1,4 @@ -Name:Gorilla +Name:Gorilla Token ManaCost:no cost PT:2/2 Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_lizard.txt b/forge-gui/res/tokenscripts/g_2_2_lizard.txt index 5d7c15b0380..ab5adb3810a 100644 --- a/forge-gui/res/tokenscripts/g_2_2_lizard.txt +++ b/forge-gui/res/tokenscripts/g_2_2_lizard.txt @@ -1,4 +1,4 @@ -Name:Lizard +Name:Lizard Token ManaCost:no cost PT:2/2 Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_monkey.txt b/forge-gui/res/tokenscripts/g_2_2_monkey.txt index 224df732582..77084c82af9 100644 --- a/forge-gui/res/tokenscripts/g_2_2_monkey.txt +++ b/forge-gui/res/tokenscripts/g_2_2_monkey.txt @@ -1,4 +1,4 @@ -Name:Monkey +Name:Monkey Token ManaCost:no cost PT:2/2 Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_ooze.txt b/forge-gui/res/tokenscripts/g_2_2_ooze.txt index c4efe4a68b8..c76ea06a214 100644 --- a/forge-gui/res/tokenscripts/g_2_2_ooze.txt +++ b/forge-gui/res/tokenscripts/g_2_2_ooze.txt @@ -1,4 +1,4 @@ -Name:Ooze +Name:Ooze Token ManaCost:no cost Types:Creature Ooze Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_ooze_mitotic.txt b/forge-gui/res/tokenscripts/g_2_2_ooze_mitotic.txt index d3a10f42e9f..4513dacb41f 100644 --- a/forge-gui/res/tokenscripts/g_2_2_ooze_mitotic.txt +++ b/forge-gui/res/tokenscripts/g_2_2_ooze_mitotic.txt @@ -1,4 +1,4 @@ -Name:Ooze +Name:Ooze Token ManaCost:no cost Types:Creature Ooze Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_rabid_sheep.txt b/forge-gui/res/tokenscripts/g_2_2_rabid_sheep.txt index 1247398ca68..26941ff98e2 100644 --- a/forge-gui/res/tokenscripts/g_2_2_rabid_sheep.txt +++ b/forge-gui/res/tokenscripts/g_2_2_rabid_sheep.txt @@ -1,4 +1,4 @@ -Name:Rabid Sheep +Name:Rabid Sheep Token ManaCost:no cost PT:2/2 Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_2_wolf.txt b/forge-gui/res/tokenscripts/g_2_2_wolf.txt index 52e24f26dc8..bd796620ef5 100644 --- a/forge-gui/res/tokenscripts/g_2_2_wolf.txt +++ b/forge-gui/res/tokenscripts/g_2_2_wolf.txt @@ -1,4 +1,4 @@ -Name:Wolf +Name:Wolf Token ManaCost:no cost PT:2/2 Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_3_antelope_forestwalk.txt b/forge-gui/res/tokenscripts/g_2_3_antelope_forestwalk.txt index daabe14169c..ffba915914b 100644 --- a/forge-gui/res/tokenscripts/g_2_3_antelope_forestwalk.txt +++ b/forge-gui/res/tokenscripts/g_2_3_antelope_forestwalk.txt @@ -1,4 +1,4 @@ -Name:Antelope +Name:Antelope Token ManaCost:no cost Types:Creature Antelope Colors:green diff --git a/forge-gui/res/tokenscripts/g_2_5_treefolk_shaman.txt b/forge-gui/res/tokenscripts/g_2_5_treefolk_shaman.txt index 830e82c1094..9f79d280eba 100644 --- a/forge-gui/res/tokenscripts/g_2_5_treefolk_shaman.txt +++ b/forge-gui/res/tokenscripts/g_2_5_treefolk_shaman.txt @@ -1,4 +1,4 @@ -Name:Treefolk Shaman +Name:Treefolk Shaman Token ManaCost:no cost PT:2/5 Colors:green diff --git a/forge-gui/res/tokenscripts/g_3_1_boar.txt b/forge-gui/res/tokenscripts/g_3_1_boar.txt index b7a83de9d3c..18a113bc724 100644 --- a/forge-gui/res/tokenscripts/g_3_1_boar.txt +++ b/forge-gui/res/tokenscripts/g_3_1_boar.txt @@ -1,4 +1,4 @@ -Name:Boar +Name:Boar Token Colors:green ManaCost:no cost PT:3/1 diff --git a/forge-gui/res/tokenscripts/g_3_2_cat_shroud.txt b/forge-gui/res/tokenscripts/g_3_2_cat_shroud.txt index 39f0955869d..c8031e4a07d 100644 --- a/forge-gui/res/tokenscripts/g_3_2_cat_shroud.txt +++ b/forge-gui/res/tokenscripts/g_3_2_cat_shroud.txt @@ -1,4 +1,4 @@ -Name:Cat +Name:Cat Token ManaCost:no cost Types:Creature Cat Colors:green diff --git a/forge-gui/res/tokenscripts/g_3_3_ape.txt b/forge-gui/res/tokenscripts/g_3_3_ape.txt index e0eb4c9e9d3..cb4fd9bcb1f 100644 --- a/forge-gui/res/tokenscripts/g_3_3_ape.txt +++ b/forge-gui/res/tokenscripts/g_3_3_ape.txt @@ -1,4 +1,4 @@ -Name:Ape +Name:Ape Token Colors:green ManaCost:no cost PT:3/3 diff --git a/forge-gui/res/tokenscripts/g_3_3_beast.txt b/forge-gui/res/tokenscripts/g_3_3_beast.txt index 80918b83e63..bd62186be4f 100644 --- a/forge-gui/res/tokenscripts/g_3_3_beast.txt +++ b/forge-gui/res/tokenscripts/g_3_3_beast.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token Colors:green ManaCost:no cost PT:3/3 diff --git a/forge-gui/res/tokenscripts/g_3_3_boar.txt b/forge-gui/res/tokenscripts/g_3_3_boar.txt index 87e0fca90e6..6c4e0c27269 100644 --- a/forge-gui/res/tokenscripts/g_3_3_boar.txt +++ b/forge-gui/res/tokenscripts/g_3_3_boar.txt @@ -1,4 +1,4 @@ -Name:Boar +Name:Boar Token Colors:green ManaCost:no cost PT:3/3 diff --git a/forge-gui/res/tokenscripts/g_3_3_centaur.txt b/forge-gui/res/tokenscripts/g_3_3_centaur.txt index ec27c18db6a..33f5b4d6b56 100644 --- a/forge-gui/res/tokenscripts/g_3_3_centaur.txt +++ b/forge-gui/res/tokenscripts/g_3_3_centaur.txt @@ -1,4 +1,4 @@ -Name:Centaur +Name:Centaur Token ManaCost:no cost Types:Creature Centaur Colors:green diff --git a/forge-gui/res/tokenscripts/g_3_3_centaur_pro_black.txt b/forge-gui/res/tokenscripts/g_3_3_centaur_pro_black.txt index d2788e73c36..1ef8280ccda 100644 --- a/forge-gui/res/tokenscripts/g_3_3_centaur_pro_black.txt +++ b/forge-gui/res/tokenscripts/g_3_3_centaur_pro_black.txt @@ -1,4 +1,4 @@ -Name:Centaur +Name:Centaur Token ManaCost:no cost Types:Creature Centaur Colors:green diff --git a/forge-gui/res/tokenscripts/g_3_3_dinosaur_trample.txt b/forge-gui/res/tokenscripts/g_3_3_dinosaur_trample.txt index 0c1f2614b54..1eb3fdfcd8e 100644 --- a/forge-gui/res/tokenscripts/g_3_3_dinosaur_trample.txt +++ b/forge-gui/res/tokenscripts/g_3_3_dinosaur_trample.txt @@ -1,4 +1,4 @@ -Name:Dinosaur +Name:Dinosaur Token ManaCost:no cost Types:Creature Dinosaur Colors:green diff --git a/forge-gui/res/tokenscripts/g_3_3_e_centaur.txt b/forge-gui/res/tokenscripts/g_3_3_e_centaur.txt index 95d180920cf..c1a65823166 100644 --- a/forge-gui/res/tokenscripts/g_3_3_e_centaur.txt +++ b/forge-gui/res/tokenscripts/g_3_3_e_centaur.txt @@ -1,4 +1,4 @@ -Name:Centaur +Name:Centaur Token ManaCost:no cost Types:Enchantment Creature Centaur Colors:green diff --git a/forge-gui/res/tokenscripts/g_3_3_elemental.txt b/forge-gui/res/tokenscripts/g_3_3_elemental.txt index a0206d970bc..924f6e853c0 100644 --- a/forge-gui/res/tokenscripts/g_3_3_elemental.txt +++ b/forge-gui/res/tokenscripts/g_3_3_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token Colors:green ManaCost:no cost PT:3/3 diff --git a/forge-gui/res/tokenscripts/g_3_3_elephant.txt b/forge-gui/res/tokenscripts/g_3_3_elephant.txt index 7e567eb1697..75315a55aab 100644 --- a/forge-gui/res/tokenscripts/g_3_3_elephant.txt +++ b/forge-gui/res/tokenscripts/g_3_3_elephant.txt @@ -1,4 +1,4 @@ -Name:Elephant +Name:Elephant Token Colors:green ManaCost:no cost PT:3/3 diff --git a/forge-gui/res/tokenscripts/g_3_3_frog_lizard.txt b/forge-gui/res/tokenscripts/g_3_3_frog_lizard.txt index 4e6e14455ca..6b289469556 100644 --- a/forge-gui/res/tokenscripts/g_3_3_frog_lizard.txt +++ b/forge-gui/res/tokenscripts/g_3_3_frog_lizard.txt @@ -1,4 +1,4 @@ -Name:Frog Lizard +Name:Frog Lizard Token Colors:green ManaCost:no cost PT:3/3 diff --git a/forge-gui/res/tokenscripts/g_3_3_hippo.txt b/forge-gui/res/tokenscripts/g_3_3_hippo.txt index 1edb56724ec..cfade5d9e48 100644 --- a/forge-gui/res/tokenscripts/g_3_3_hippo.txt +++ b/forge-gui/res/tokenscripts/g_3_3_hippo.txt @@ -1,4 +1,4 @@ -Name:Hippo +Name:Hippo Token ManaCost:no cost Types:Creature Hippo Colors:green diff --git a/forge-gui/res/tokenscripts/g_3_3_insect.txt b/forge-gui/res/tokenscripts/g_3_3_insect.txt index 7cdcbf926f6..17f34350496 100644 --- a/forge-gui/res/tokenscripts/g_3_3_insect.txt +++ b/forge-gui/res/tokenscripts/g_3_3_insect.txt @@ -1,4 +1,4 @@ -Name:Insect +Name:Insect Token ManaCost:no cost Types:Creature Insect Colors:green diff --git a/forge-gui/res/tokenscripts/g_3_3_ooze.txt b/forge-gui/res/tokenscripts/g_3_3_ooze.txt index 59cdcff7d87..95f7c5c0cb0 100644 --- a/forge-gui/res/tokenscripts/g_3_3_ooze.txt +++ b/forge-gui/res/tokenscripts/g_3_3_ooze.txt @@ -1,4 +1,4 @@ -Name:Ooze +Name:Ooze Token ManaCost:no cost Types:Creature Ooze Colors:green diff --git a/forge-gui/res/tokenscripts/g_4_2_beast.txt b/forge-gui/res/tokenscripts/g_4_2_beast.txt index c129ad749fc..4b41a837690 100644 --- a/forge-gui/res/tokenscripts/g_4_2_beast.txt +++ b/forge-gui/res/tokenscripts/g_4_2_beast.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token Colors:green ManaCost:no cost PT:4/2 diff --git a/forge-gui/res/tokenscripts/g_4_4_bear.txt b/forge-gui/res/tokenscripts/g_4_4_bear.txt index 6e68d86fd37..cbec9341a43 100644 --- a/forge-gui/res/tokenscripts/g_4_4_bear.txt +++ b/forge-gui/res/tokenscripts/g_4_4_bear.txt @@ -1,4 +1,4 @@ -Name:Bear +Name:Bear Token Colors:green ManaCost:no cost PT:4/4 diff --git a/forge-gui/res/tokenscripts/g_4_4_beast.txt b/forge-gui/res/tokenscripts/g_4_4_beast.txt index 17f15ef4e8e..5aeb9801d42 100644 --- a/forge-gui/res/tokenscripts/g_4_4_beast.txt +++ b/forge-gui/res/tokenscripts/g_4_4_beast.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token Colors:green ManaCost:no cost PT:4/4 diff --git a/forge-gui/res/tokenscripts/g_4_4_elemental.txt b/forge-gui/res/tokenscripts/g_4_4_elemental.txt index 9bcbbbc547f..3e01c78ecd7 100644 --- a/forge-gui/res/tokenscripts/g_4_4_elemental.txt +++ b/forge-gui/res/tokenscripts/g_4_4_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token Colors:green ManaCost:no cost PT:4/4 diff --git a/forge-gui/res/tokenscripts/g_4_4_fungus_beast_trample.txt b/forge-gui/res/tokenscripts/g_4_4_fungus_beast_trample.txt index d81c5a89537..4c6f740e270 100644 --- a/forge-gui/res/tokenscripts/g_4_4_fungus_beast_trample.txt +++ b/forge-gui/res/tokenscripts/g_4_4_fungus_beast_trample.txt @@ -1,4 +1,4 @@ -Name:Fungus Beast +Name:Fungus Beast Token Colors:green ManaCost:no cost PT:4/4 diff --git a/forge-gui/res/tokenscripts/g_4_4_phyrexian_beast.txt b/forge-gui/res/tokenscripts/g_4_4_phyrexian_beast.txt index 34ac0ee0ca8..db4270bad3c 100644 --- a/forge-gui/res/tokenscripts/g_4_4_phyrexian_beast.txt +++ b/forge-gui/res/tokenscripts/g_4_4_phyrexian_beast.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Beast +Name:Phyrexian Beast Token Colors:green ManaCost:no cost PT:4/4 diff --git a/forge-gui/res/tokenscripts/g_4_4_rhino_trample.txt b/forge-gui/res/tokenscripts/g_4_4_rhino_trample.txt index 997e813a90f..79123eddbf0 100644 --- a/forge-gui/res/tokenscripts/g_4_4_rhino_trample.txt +++ b/forge-gui/res/tokenscripts/g_4_4_rhino_trample.txt @@ -1,4 +1,4 @@ -Name:Rhino +Name:Rhino Token Colors:green ManaCost:no cost PT:4/4 diff --git a/forge-gui/res/tokenscripts/g_4_4_troll_warrior_trample.txt b/forge-gui/res/tokenscripts/g_4_4_troll_warrior_trample.txt index c2251c78dba..570c6e08caf 100644 --- a/forge-gui/res/tokenscripts/g_4_4_troll_warrior_trample.txt +++ b/forge-gui/res/tokenscripts/g_4_4_troll_warrior_trample.txt @@ -1,4 +1,4 @@ -Name:Troll Warrior +Name:Troll Warrior Token Colors:green ManaCost:no cost PT:4/4 diff --git a/forge-gui/res/tokenscripts/g_5_3_elemental.txt b/forge-gui/res/tokenscripts/g_5_3_elemental.txt index 84c0fa1cc30..bdfa4a9bd8a 100644 --- a/forge-gui/res/tokenscripts/g_5_3_elemental.txt +++ b/forge-gui/res/tokenscripts/g_5_3_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token Colors:green ManaCost:no cost PT:5/3 diff --git a/forge-gui/res/tokenscripts/g_5_4_snake.txt b/forge-gui/res/tokenscripts/g_5_4_snake.txt index 957b1ed0352..11905a44255 100644 --- a/forge-gui/res/tokenscripts/g_5_4_snake.txt +++ b/forge-gui/res/tokenscripts/g_5_4_snake.txt @@ -1,4 +1,4 @@ -Name:Snake +Name:Snake Token ManaCost:no cost Types:Creature Snake Colors:green diff --git a/forge-gui/res/tokenscripts/g_5_5_beast.txt b/forge-gui/res/tokenscripts/g_5_5_beast.txt index 50a8be2a43a..b9105319b51 100644 --- a/forge-gui/res/tokenscripts/g_5_5_beast.txt +++ b/forge-gui/res/tokenscripts/g_5_5_beast.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token Colors:green ManaCost:no cost PT:5/5 diff --git a/forge-gui/res/tokenscripts/g_5_5_beast_trample.txt b/forge-gui/res/tokenscripts/g_5_5_beast_trample.txt index 7451bd11728..b45da587ed1 100644 --- a/forge-gui/res/tokenscripts/g_5_5_beast_trample.txt +++ b/forge-gui/res/tokenscripts/g_5_5_beast_trample.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token Colors:green ManaCost:no cost PT:5/5 diff --git a/forge-gui/res/tokenscripts/g_5_5_wurm.txt b/forge-gui/res/tokenscripts/g_5_5_wurm.txt index e785ac25c92..2044fcfe805 100644 --- a/forge-gui/res/tokenscripts/g_5_5_wurm.txt +++ b/forge-gui/res/tokenscripts/g_5_5_wurm.txt @@ -1,4 +1,4 @@ -Name:Wurm +Name:Wurm Token Colors:green ManaCost:no cost PT:5/5 diff --git a/forge-gui/res/tokenscripts/g_5_5_wurm_trample.txt b/forge-gui/res/tokenscripts/g_5_5_wurm_trample.txt index d3760353cc7..1eed7c83a3e 100644 --- a/forge-gui/res/tokenscripts/g_5_5_wurm_trample.txt +++ b/forge-gui/res/tokenscripts/g_5_5_wurm_trample.txt @@ -1,4 +1,4 @@ -Name:Wurm +Name:Wurm Token Colors:green ManaCost:no cost PT:5/5 diff --git a/forge-gui/res/tokenscripts/g_6_1_insect_shroud.txt b/forge-gui/res/tokenscripts/g_6_1_insect_shroud.txt index e6448edb9f5..2ae5603debd 100644 --- a/forge-gui/res/tokenscripts/g_6_1_insect_shroud.txt +++ b/forge-gui/res/tokenscripts/g_6_1_insect_shroud.txt @@ -1,4 +1,4 @@ -Name:Insect +Name:Insect Token Colors:green ManaCost:no cost PT:6/1 diff --git a/forge-gui/res/tokenscripts/g_6_6_wurm.txt b/forge-gui/res/tokenscripts/g_6_6_wurm.txt index 2fb75284dee..18517f0b3e0 100644 --- a/forge-gui/res/tokenscripts/g_6_6_wurm.txt +++ b/forge-gui/res/tokenscripts/g_6_6_wurm.txt @@ -1,4 +1,4 @@ -Name:Wurm +Name:Wurm Token Colors:green ManaCost:no cost PT:6/6 diff --git a/forge-gui/res/tokenscripts/g_7_7_elemental_trample.txt b/forge-gui/res/tokenscripts/g_7_7_elemental_trample.txt index 997b8b16391..66d6f09f69b 100644 --- a/forge-gui/res/tokenscripts/g_7_7_elemental_trample.txt +++ b/forge-gui/res/tokenscripts/g_7_7_elemental_trample.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token Colors:green ManaCost:no cost PT:7/7 diff --git a/forge-gui/res/tokenscripts/g_7_7_giant.txt b/forge-gui/res/tokenscripts/g_7_7_giant.txt index ab0ad7d07b6..c60bec17e33 100644 --- a/forge-gui/res/tokenscripts/g_7_7_giant.txt +++ b/forge-gui/res/tokenscripts/g_7_7_giant.txt @@ -1,4 +1,4 @@ -Name:Giant +Name:Giant Token Colors:green ManaCost:no cost PT:7/7 diff --git a/forge-gui/res/tokenscripts/g_x_x_dinosaur_beast_trample.txt b/forge-gui/res/tokenscripts/g_x_x_dinosaur_beast_trample.txt index 967d820125a..822fb02809e 100644 --- a/forge-gui/res/tokenscripts/g_x_x_dinosaur_beast_trample.txt +++ b/forge-gui/res/tokenscripts/g_x_x_dinosaur_beast_trample.txt @@ -1,4 +1,4 @@ -Name:Dinosaur Beast +Name:Dinosaur Beast Token Colors:green ManaCost:no cost PT:*/* diff --git a/forge-gui/res/tokenscripts/g_x_x_elemental.txt b/forge-gui/res/tokenscripts/g_x_x_elemental.txt index 503369098af..ecc9fc634c3 100644 --- a/forge-gui/res/tokenscripts/g_x_x_elemental.txt +++ b/forge-gui/res/tokenscripts/g_x_x_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token Colors:green ManaCost:no cost PT:*/* diff --git a/forge-gui/res/tokenscripts/g_x_x_elephant_resurgence.txt b/forge-gui/res/tokenscripts/g_x_x_elephant_resurgence.txt index 9b2d3f08bd2..ce3b27e6724 100644 --- a/forge-gui/res/tokenscripts/g_x_x_elephant_resurgence.txt +++ b/forge-gui/res/tokenscripts/g_x_x_elephant_resurgence.txt @@ -1,4 +1,4 @@ -Name:Elephant +Name:Elephant Token ManaCost:no cost Types:Creature Elephant Colors:green diff --git a/forge-gui/res/tokenscripts/g_x_x_hydra.txt b/forge-gui/res/tokenscripts/g_x_x_hydra.txt index 75e87378d67..d5010d4dae4 100644 --- a/forge-gui/res/tokenscripts/g_x_x_hydra.txt +++ b/forge-gui/res/tokenscripts/g_x_x_hydra.txt @@ -1,4 +1,4 @@ -Name:Hydra +Name:Hydra Token Colors:green ManaCost:no cost PT:*/* diff --git a/forge-gui/res/tokenscripts/g_x_x_ooze.txt b/forge-gui/res/tokenscripts/g_x_x_ooze.txt index d5aa4f030af..0890a039428 100644 --- a/forge-gui/res/tokenscripts/g_x_x_ooze.txt +++ b/forge-gui/res/tokenscripts/g_x_x_ooze.txt @@ -1,4 +1,4 @@ -Name:Ooze +Name:Ooze Token ManaCost:no cost Types:Creature Ooze Colors:green diff --git a/forge-gui/res/tokenscripts/g_x_x_ooze_gutter_grime.txt b/forge-gui/res/tokenscripts/g_x_x_ooze_gutter_grime.txt index 1c3c11e515e..dcd54e755aa 100644 --- a/forge-gui/res/tokenscripts/g_x_x_ooze_gutter_grime.txt +++ b/forge-gui/res/tokenscripts/g_x_x_ooze_gutter_grime.txt @@ -1,4 +1,4 @@ -Name:Ooze +Name:Ooze Token ManaCost:no cost Types:Creature Ooze Colors:green diff --git a/forge-gui/res/tokenscripts/g_x_x_saproling_burst.txt b/forge-gui/res/tokenscripts/g_x_x_saproling_burst.txt index c915f667b23..6bc4aec9902 100644 --- a/forge-gui/res/tokenscripts/g_x_x_saproling_burst.txt +++ b/forge-gui/res/tokenscripts/g_x_x_saproling_burst.txt @@ -1,4 +1,4 @@ -Name:Saproling +Name:Saproling Token ManaCost:no cost Types:Creature Saproling Colors:green diff --git a/forge-gui/res/tokenscripts/g_x_x_treefolk.txt b/forge-gui/res/tokenscripts/g_x_x_treefolk.txt index c0a5e833252..1a991e94fd1 100644 --- a/forge-gui/res/tokenscripts/g_x_x_treefolk.txt +++ b/forge-gui/res/tokenscripts/g_x_x_treefolk.txt @@ -1,4 +1,4 @@ -Name:Treefolk +Name:Treefolk Token ManaCost:no cost Types:Creature Treefolk Colors:green diff --git a/forge-gui/res/tokenscripts/g_x_x_treefolk_reach_total_lands.txt b/forge-gui/res/tokenscripts/g_x_x_treefolk_reach_total_lands.txt index 9e0fcff193b..46e60946d33 100644 --- a/forge-gui/res/tokenscripts/g_x_x_treefolk_reach_total_lands.txt +++ b/forge-gui/res/tokenscripts/g_x_x_treefolk_reach_total_lands.txt @@ -1,4 +1,4 @@ -Name:Treefolk +Name:Treefolk Token ManaCost:no cost Types:Creature Treefolk Colors:green diff --git a/forge-gui/res/tokenscripts/g_x_x_treefolk_warrior_total_forests.txt b/forge-gui/res/tokenscripts/g_x_x_treefolk_warrior_total_forests.txt index f7306c11a14..136c3e3133a 100644 --- a/forge-gui/res/tokenscripts/g_x_x_treefolk_warrior_total_forests.txt +++ b/forge-gui/res/tokenscripts/g_x_x_treefolk_warrior_total_forests.txt @@ -1,4 +1,4 @@ -Name:Treefolk Warrior +Name:Treefolk Warrior Token ManaCost:no cost Types:Creature Treefolk Warrior Colors:green diff --git a/forge-gui/res/tokenscripts/g_x_x_wurm.txt b/forge-gui/res/tokenscripts/g_x_x_wurm.txt index dae24fc861e..2c8035ddd2b 100644 --- a/forge-gui/res/tokenscripts/g_x_x_wurm.txt +++ b/forge-gui/res/tokenscripts/g_x_x_wurm.txt @@ -1,4 +1,4 @@ -Name:Wurm +Name:Wurm Token Colors:green ManaCost:no cost PT:*/* diff --git a/forge-gui/res/tokenscripts/g_x_y_ooze_types_graveyard.txt b/forge-gui/res/tokenscripts/g_x_y_ooze_types_graveyard.txt index 5e3a153df52..0578dd8011a 100644 --- a/forge-gui/res/tokenscripts/g_x_y_ooze_types_graveyard.txt +++ b/forge-gui/res/tokenscripts/g_x_y_ooze_types_graveyard.txt @@ -1,4 +1,4 @@ -Name:Ooze +Name:Ooze Token ManaCost:no cost Types:Creature Ooze Colors:green diff --git a/forge-gui/res/tokenscripts/goldmeadow_harrier.txt b/forge-gui/res/tokenscripts/goldmeadow_harrier.txt index 0abc5d8429a..40832a41c72 100644 --- a/forge-gui/res/tokenscripts/goldmeadow_harrier.txt +++ b/forge-gui/res/tokenscripts/goldmeadow_harrier.txt @@ -5,4 +5,4 @@ PT:1/1 Types:Creature Kithkin Soldier A:AB$ Tap | Cost$ W T | ValidTgts$ Creature | TgtPrompt$ Select target creature | SpellDescription$ Tap target creature. SVar:NonCombatPriority:1 -Oracle:{W}, {T}: Tap target creature. \ No newline at end of file +Oracle:{W}, {T}: Tap target creature. diff --git a/forge-gui/res/tokenscripts/gu_0_0_fractal.txt b/forge-gui/res/tokenscripts/gu_0_0_fractal.txt index a953e6679f0..cf7dbbdbfcd 100644 --- a/forge-gui/res/tokenscripts/gu_0_0_fractal.txt +++ b/forge-gui/res/tokenscripts/gu_0_0_fractal.txt @@ -1,4 +1,4 @@ -Name:Fractal +Name:Fractal Token Colors:green,blue ManaCost:no cost Types:Creature Fractal diff --git a/forge-gui/res/tokenscripts/gu_1_1_snake.txt b/forge-gui/res/tokenscripts/gu_1_1_snake.txt index 92549ec3db9..526b165b7d0 100644 --- a/forge-gui/res/tokenscripts/gu_1_1_snake.txt +++ b/forge-gui/res/tokenscripts/gu_1_1_snake.txt @@ -1,4 +1,4 @@ -Name:Snake +Name:Snake Token Colors:green,blue ManaCost:no cost PT:1/1 diff --git a/forge-gui/res/tokenscripts/gu_2_2_drake_flying.txt b/forge-gui/res/tokenscripts/gu_2_2_drake_flying.txt index 683cd19435f..045e3d9e644 100644 --- a/forge-gui/res/tokenscripts/gu_2_2_drake_flying.txt +++ b/forge-gui/res/tokenscripts/gu_2_2_drake_flying.txt @@ -1,4 +1,4 @@ -Name:Drake +Name:Drake Token Colors:green,blue ManaCost:no cost PT:2/2 diff --git a/forge-gui/res/tokenscripts/gw_1_1_elf_warrior.txt b/forge-gui/res/tokenscripts/gw_1_1_elf_warrior.txt index 2cf9cf1b23b..ce14d6e69c8 100644 --- a/forge-gui/res/tokenscripts/gw_1_1_elf_warrior.txt +++ b/forge-gui/res/tokenscripts/gw_1_1_elf_warrior.txt @@ -1,4 +1,4 @@ -Name:Elf Warrior +Name:Elf Warrior Token ManaCost:no cost Types:Creature Elf Warrior Colors:green,white diff --git a/forge-gui/res/tokenscripts/gw_1_1_human_soldier_training.txt b/forge-gui/res/tokenscripts/gw_1_1_human_soldier_training.txt index dd45be9288e..834b540f625 100644 --- a/forge-gui/res/tokenscripts/gw_1_1_human_soldier_training.txt +++ b/forge-gui/res/tokenscripts/gw_1_1_human_soldier_training.txt @@ -1,4 +1,4 @@ -Name:Human Soldier +Name:Human Soldier Token ManaCost:no cost Types:Creature Human Soldier Colors:white,green diff --git a/forge-gui/res/tokenscripts/gw_2_2_elf_knight_vigilance.txt b/forge-gui/res/tokenscripts/gw_2_2_elf_knight_vigilance.txt index eaaee6f4d5f..e2dccf349f5 100644 --- a/forge-gui/res/tokenscripts/gw_2_2_elf_knight_vigilance.txt +++ b/forge-gui/res/tokenscripts/gw_2_2_elf_knight_vigilance.txt @@ -1,4 +1,4 @@ -Name:Elf Knight +Name:Elf Knight Token ManaCost:no cost Types:Creature Elf Knight Colors:white,green diff --git a/forge-gui/res/tokenscripts/gw_8_8_elemental_vigilance.txt b/forge-gui/res/tokenscripts/gw_8_8_elemental_vigilance.txt index 21f7b8ef1a1..baac697c3c7 100644 --- a/forge-gui/res/tokenscripts/gw_8_8_elemental_vigilance.txt +++ b/forge-gui/res/tokenscripts/gw_8_8_elemental_vigilance.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:green,white diff --git a/forge-gui/res/tokenscripts/gw_x_x_elemental_total_creatures.txt b/forge-gui/res/tokenscripts/gw_x_x_elemental_total_creatures.txt index d28c12f53fc..87f6bec3e66 100644 --- a/forge-gui/res/tokenscripts/gw_x_x_elemental_total_creatures.txt +++ b/forge-gui/res/tokenscripts/gw_x_x_elemental_total_creatures.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:green,white diff --git a/forge-gui/res/tokenscripts/r_0_1_elemental_rekindling_phoenix.txt b/forge-gui/res/tokenscripts/r_0_1_elemental_rekindling_phoenix.txt index bd3fc89b14a..f0a3941c29e 100644 --- a/forge-gui/res/tokenscripts/r_0_1_elemental_rekindling_phoenix.txt +++ b/forge-gui/res/tokenscripts/r_0_1_elemental_rekindling_phoenix.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_0_2_dragon_egg_defender_hatches_dragon.txt b/forge-gui/res/tokenscripts/r_0_2_dragon_egg_defender_hatches_dragon.txt index a5a98016396..81ef0348343 100644 --- a/forge-gui/res/tokenscripts/r_0_2_dragon_egg_defender_hatches_dragon.txt +++ b/forge-gui/res/tokenscripts/r_0_2_dragon_egg_defender_hatches_dragon.txt @@ -1,4 +1,4 @@ -Name:Dragon Egg +Name:Dragon Egg Token ManaCost:no cost Types:Creature Dragon Egg Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_brainiac.txt b/forge-gui/res/tokenscripts/r_1_1_brainiac.txt index 7dcd90e02fa..73f10edb691 100644 --- a/forge-gui/res/tokenscripts/r_1_1_brainiac.txt +++ b/forge-gui/res/tokenscripts/r_1_1_brainiac.txt @@ -1,4 +1,4 @@ -Name:Brainiac +Name:Brainiac Token ManaCost:no cost Types:Creature Brainiac Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_devil_burn.txt b/forge-gui/res/tokenscripts/r_1_1_devil_burn.txt index bf978b9e4a1..aeade1e9374 100644 --- a/forge-gui/res/tokenscripts/r_1_1_devil_burn.txt +++ b/forge-gui/res/tokenscripts/r_1_1_devil_burn.txt @@ -1,4 +1,4 @@ -Name:Devil +Name:Devil Token ManaCost:no cost Types:Creature Devil Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_dinosaur_haste.txt b/forge-gui/res/tokenscripts/r_1_1_dinosaur_haste.txt index 6c3201e848c..091b80905dc 100644 --- a/forge-gui/res/tokenscripts/r_1_1_dinosaur_haste.txt +++ b/forge-gui/res/tokenscripts/r_1_1_dinosaur_haste.txt @@ -1,4 +1,4 @@ -Name:Dinosaur +Name:Dinosaur Token ManaCost:no cost Types:Creature Dinosaur Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_dwarf.txt b/forge-gui/res/tokenscripts/r_1_1_dwarf.txt index f6ff5776ddf..f28138dbcf3 100644 --- a/forge-gui/res/tokenscripts/r_1_1_dwarf.txt +++ b/forge-gui/res/tokenscripts/r_1_1_dwarf.txt @@ -1,4 +1,4 @@ -Name:Dwarf +Name:Dwarf Token ManaCost:no cost Types:Creature Dwarf Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_elemental.txt b/forge-gui/res/tokenscripts/r_1_1_elemental.txt index efe72783d4f..b92f37adfd8 100644 --- a/forge-gui/res/tokenscripts/r_1_1_elemental.txt +++ b/forge-gui/res/tokenscripts/r_1_1_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_elemental_cat_haste.txt b/forge-gui/res/tokenscripts/r_1_1_elemental_cat_haste.txt index 4f698519083..bbb4bb8f3fb 100644 --- a/forge-gui/res/tokenscripts/r_1_1_elemental_cat_haste.txt +++ b/forge-gui/res/tokenscripts/r_1_1_elemental_cat_haste.txt @@ -1,4 +1,4 @@ -Name:Elemental Cat +Name:Elemental Cat Token ManaCost:no cost Types:Creature Elemental Cat Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_elemental_haste.txt b/forge-gui/res/tokenscripts/r_1_1_elemental_haste.txt index f7364348803..37ff90c6f46 100644 --- a/forge-gui/res/tokenscripts/r_1_1_elemental_haste.txt +++ b/forge-gui/res/tokenscripts/r_1_1_elemental_haste.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_goblin.txt b/forge-gui/res/tokenscripts/r_1_1_goblin.txt index a3a9b86f144..5d50b83b61f 100644 --- a/forge-gui/res/tokenscripts/r_1_1_goblin.txt +++ b/forge-gui/res/tokenscripts/r_1_1_goblin.txt @@ -1,4 +1,4 @@ -Name:Goblin +Name:Goblin Token ManaCost:no cost Types:Creature Goblin Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_goblin_all_attack.txt b/forge-gui/res/tokenscripts/r_1_1_goblin_all_attack.txt index 159c4031847..4cd16716254 100644 --- a/forge-gui/res/tokenscripts/r_1_1_goblin_all_attack.txt +++ b/forge-gui/res/tokenscripts/r_1_1_goblin_all_attack.txt @@ -1,4 +1,4 @@ -Name:Goblin +Name:Goblin Token ManaCost:no cost Types:Creature Goblin Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_goblin_haste.txt b/forge-gui/res/tokenscripts/r_1_1_goblin_haste.txt index cc5b6c1ba9c..6b92f749fb0 100644 --- a/forge-gui/res/tokenscripts/r_1_1_goblin_haste.txt +++ b/forge-gui/res/tokenscripts/r_1_1_goblin_haste.txt @@ -1,4 +1,4 @@ -Name:Goblin +Name:Goblin Token ManaCost:no cost Types:Creature Goblin Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_goblin_noblock.txt b/forge-gui/res/tokenscripts/r_1_1_goblin_noblock.txt index 4cfb1532642..47e58f1539d 100644 --- a/forge-gui/res/tokenscripts/r_1_1_goblin_noblock.txt +++ b/forge-gui/res/tokenscripts/r_1_1_goblin_noblock.txt @@ -1,4 +1,4 @@ -Name:Goblin +Name:Goblin Token ManaCost:no cost Types:Creature Goblin Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_goblin_scout_mountainwalk.txt b/forge-gui/res/tokenscripts/r_1_1_goblin_scout_mountainwalk.txt index d5e56a73ae8..2ece14ca284 100644 --- a/forge-gui/res/tokenscripts/r_1_1_goblin_scout_mountainwalk.txt +++ b/forge-gui/res/tokenscripts/r_1_1_goblin_scout_mountainwalk.txt @@ -1,4 +1,4 @@ -Name:Goblin Scout +Name:Goblin Scout Token ManaCost:no cost Types:Creature Goblin Scout Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_goblin_wizard_prowess.txt b/forge-gui/res/tokenscripts/r_1_1_goblin_wizard_prowess.txt index 9115ad3a6f6..11c7f1bebf5 100644 --- a/forge-gui/res/tokenscripts/r_1_1_goblin_wizard_prowess.txt +++ b/forge-gui/res/tokenscripts/r_1_1_goblin_wizard_prowess.txt @@ -1,4 +1,4 @@ -Name:Goblin Wizard +Name:Goblin Wizard Token ManaCost:no cost Types:Creature Goblin Wizard Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_human.txt b/forge-gui/res/tokenscripts/r_1_1_human.txt index 7a3d68e19d5..82924738a0a 100644 --- a/forge-gui/res/tokenscripts/r_1_1_human.txt +++ b/forge-gui/res/tokenscripts/r_1_1_human.txt @@ -1,4 +1,4 @@ -Name:Human +Name:Human Token ManaCost:no cost Types:Creature Human Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_human_haste.txt b/forge-gui/res/tokenscripts/r_1_1_human_haste.txt index 487e4b7d8ce..0398746c2b9 100644 --- a/forge-gui/res/tokenscripts/r_1_1_human_haste.txt +++ b/forge-gui/res/tokenscripts/r_1_1_human_haste.txt @@ -1,4 +1,4 @@ -Name:Human +Name:Human Token ManaCost:no cost Types:Creature Human Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_phyrexian_goblin_haste.txt b/forge-gui/res/tokenscripts/r_1_1_phyrexian_goblin_haste.txt index db3fe5ebcbf..59dec950af0 100644 --- a/forge-gui/res/tokenscripts/r_1_1_phyrexian_goblin_haste.txt +++ b/forge-gui/res/tokenscripts/r_1_1_phyrexian_goblin_haste.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Goblin +Name:Phyrexian Goblin Token ManaCost:no cost Types:Creature Phyrexian Goblin Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_pirate_noblock_all_attack.txt b/forge-gui/res/tokenscripts/r_1_1_pirate_noblock_all_attack.txt index 36de06e5efe..68957ac1ee1 100644 --- a/forge-gui/res/tokenscripts/r_1_1_pirate_noblock_all_attack.txt +++ b/forge-gui/res/tokenscripts/r_1_1_pirate_noblock_all_attack.txt @@ -1,4 +1,4 @@ -Name:Pirate +Name:Pirate Token ManaCost:no cost Types:Creature Pirate Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_satyr_noblock.txt b/forge-gui/res/tokenscripts/r_1_1_satyr_noblock.txt index 686eb9da76f..3311f4fca39 100644 --- a/forge-gui/res/tokenscripts/r_1_1_satyr_noblock.txt +++ b/forge-gui/res/tokenscripts/r_1_1_satyr_noblock.txt @@ -1,4 +1,4 @@ -Name:Satyr +Name:Satyr Token ManaCost:no cost Types:Creature Satyr Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_soldier_haste.txt b/forge-gui/res/tokenscripts/r_1_1_soldier_haste.txt index 3a1aecb29a2..80098aefb6c 100644 --- a/forge-gui/res/tokenscripts/r_1_1_soldier_haste.txt +++ b/forge-gui/res/tokenscripts/r_1_1_soldier_haste.txt @@ -1,4 +1,4 @@ -Name:Soldier +Name:Soldier Token ManaCost:no cost Types:Creature Soldier Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_survivor.txt b/forge-gui/res/tokenscripts/r_1_1_survivor.txt index 72207b2f291..590edf5b9e6 100644 --- a/forge-gui/res/tokenscripts/r_1_1_survivor.txt +++ b/forge-gui/res/tokenscripts/r_1_1_survivor.txt @@ -1,4 +1,4 @@ -Name:Survivor +Name:Survivor Token ManaCost:no cost Types:Creature Survivor Colors:red diff --git a/forge-gui/res/tokenscripts/r_1_1_warrior.txt b/forge-gui/res/tokenscripts/r_1_1_warrior.txt index 31c2d297ca9..14abfa95125 100644 --- a/forge-gui/res/tokenscripts/r_1_1_warrior.txt +++ b/forge-gui/res/tokenscripts/r_1_1_warrior.txt @@ -1,4 +1,4 @@ -Name:Warrior +Name:Warrior Token ManaCost:no cost Types:Creature Warrior Colors:red diff --git a/forge-gui/res/tokenscripts/r_2_1_dwarf_berserker.txt b/forge-gui/res/tokenscripts/r_2_1_dwarf_berserker.txt index 556b17128fe..97ef32476cf 100644 --- a/forge-gui/res/tokenscripts/r_2_1_dwarf_berserker.txt +++ b/forge-gui/res/tokenscripts/r_2_1_dwarf_berserker.txt @@ -1,4 +1,4 @@ -Name:Dwarf Berserker +Name:Dwarf Berserker Token ManaCost:no cost Types:Creature Dwarf Berserker Colors:red diff --git a/forge-gui/res/tokenscripts/r_2_1_goblin_haste.txt b/forge-gui/res/tokenscripts/r_2_1_goblin_haste.txt index 22e94d31672..233f397490a 100644 --- a/forge-gui/res/tokenscripts/r_2_1_goblin_haste.txt +++ b/forge-gui/res/tokenscripts/r_2_1_goblin_haste.txt @@ -1,4 +1,4 @@ -Name:Goblin +Name:Goblin Token ManaCost:no cost Types:Creature Goblin Colors:red diff --git a/forge-gui/res/tokenscripts/r_2_1_human_wizard.txt b/forge-gui/res/tokenscripts/r_2_1_human_wizard.txt index a0ac47421e8..d393574edc6 100644 --- a/forge-gui/res/tokenscripts/r_2_1_human_wizard.txt +++ b/forge-gui/res/tokenscripts/r_2_1_human_wizard.txt @@ -1,4 +1,4 @@ -Name:Human Wizard +Name:Human Wizard Token ManaCost:no cost Types:Creature Human Wizard Colors:red diff --git a/forge-gui/res/tokenscripts/r_2_2_dragon_flying_firebreathing.txt b/forge-gui/res/tokenscripts/r_2_2_dragon_flying_firebreathing.txt index 3e5b7948d09..fe25764217c 100644 --- a/forge-gui/res/tokenscripts/r_2_2_dragon_flying_firebreathing.txt +++ b/forge-gui/res/tokenscripts/r_2_2_dragon_flying_firebreathing.txt @@ -1,4 +1,4 @@ -Name:Dragon +Name:Dragon Token ManaCost:no cost Types:Creature Dragon Colors:red diff --git a/forge-gui/res/tokenscripts/r_2_2_gremlin.txt b/forge-gui/res/tokenscripts/r_2_2_gremlin.txt index 598a3472733..bd05e347fb8 100644 --- a/forge-gui/res/tokenscripts/r_2_2_gremlin.txt +++ b/forge-gui/res/tokenscripts/r_2_2_gremlin.txt @@ -1,4 +1,4 @@ -Name:Gremlin +Name:Gremlin Token ManaCost:no cost PT:2/2 Colors:red diff --git a/forge-gui/res/tokenscripts/r_2_3_demon_berserker_menace.txt b/forge-gui/res/tokenscripts/r_2_3_demon_berserker_menace.txt index 4f6123b2bde..02fe639f443 100644 --- a/forge-gui/res/tokenscripts/r_2_3_demon_berserker_menace.txt +++ b/forge-gui/res/tokenscripts/r_2_3_demon_berserker_menace.txt @@ -1,4 +1,4 @@ -Name:Demon Berserker +Name:Demon Berserker Token ManaCost:no cost Types:Creature Demon Berserker Colors:red diff --git a/forge-gui/res/tokenscripts/r_2_3_minotaur.txt b/forge-gui/res/tokenscripts/r_2_3_minotaur.txt index 9b67ee61510..d8d39d76a25 100644 --- a/forge-gui/res/tokenscripts/r_2_3_minotaur.txt +++ b/forge-gui/res/tokenscripts/r_2_3_minotaur.txt @@ -1,4 +1,4 @@ -Name:Minotaur +Name:Minotaur Token ManaCost:no cost Types:Creature Minotaur Colors:red diff --git a/forge-gui/res/tokenscripts/r_2_3_minotaur_haste.txt b/forge-gui/res/tokenscripts/r_2_3_minotaur_haste.txt index 8813db20465..d8505805b9b 100644 --- a/forge-gui/res/tokenscripts/r_2_3_minotaur_haste.txt +++ b/forge-gui/res/tokenscripts/r_2_3_minotaur_haste.txt @@ -1,4 +1,4 @@ -Name:Minotaur +Name:Minotaur Token ManaCost:no cost Types:Creature Minotaur Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_1_e_elemental_haste.txt b/forge-gui/res/tokenscripts/r_3_1_e_elemental_haste.txt index 0fe2176a774..df6426405aa 100644 --- a/forge-gui/res/tokenscripts/r_3_1_e_elemental_haste.txt +++ b/forge-gui/res/tokenscripts/r_3_1_e_elemental_haste.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Enchantment Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_1_elemental.txt b/forge-gui/res/tokenscripts/r_3_1_elemental.txt index 2e0b11e3688..13c98c088e8 100644 --- a/forge-gui/res/tokenscripts/r_3_1_elemental.txt +++ b/forge-gui/res/tokenscripts/r_3_1_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_1_elemental_haste.txt b/forge-gui/res/tokenscripts/r_3_1_elemental_haste.txt index 9234b219ab4..ddfa4f90103 100644 --- a/forge-gui/res/tokenscripts/r_3_1_elemental_haste.txt +++ b/forge-gui/res/tokenscripts/r_3_1_elemental_haste.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_1_elemental_shaman.txt b/forge-gui/res/tokenscripts/r_3_1_elemental_shaman.txt index 295c4cc8399..64b30cc7567 100644 --- a/forge-gui/res/tokenscripts/r_3_1_elemental_shaman.txt +++ b/forge-gui/res/tokenscripts/r_3_1_elemental_shaman.txt @@ -1,4 +1,4 @@ -Name:Elemental Shaman +Name:Elemental Shaman Token ManaCost:no cost Types:Creature Elemental Shaman Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_1_elemental_shaman_haste.txt b/forge-gui/res/tokenscripts/r_3_1_elemental_shaman_haste.txt index a45e3b652ef..280acaf329e 100644 --- a/forge-gui/res/tokenscripts/r_3_1_elemental_shaman_haste.txt +++ b/forge-gui/res/tokenscripts/r_3_1_elemental_shaman_haste.txt @@ -1,4 +1,4 @@ -Name:Elemental Shaman +Name:Elemental Shaman Token ManaCost:no cost Types:Creature Elemental Shaman Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_1_elemental_trample_haste.txt b/forge-gui/res/tokenscripts/r_3_1_elemental_trample_haste.txt index c37cd3eeb6e..c991f56f220 100644 --- a/forge-gui/res/tokenscripts/r_3_1_elemental_trample_haste.txt +++ b/forge-gui/res/tokenscripts/r_3_1_elemental_trample_haste.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_2_wolf.txt b/forge-gui/res/tokenscripts/r_3_2_wolf.txt index 16d03d46c73..ce3d9515ddb 100644 --- a/forge-gui/res/tokenscripts/r_3_2_wolf.txt +++ b/forge-gui/res/tokenscripts/r_3_2_wolf.txt @@ -1,4 +1,4 @@ -Name:Wolf +Name:Wolf Token ManaCost:no cost PT:3/2 Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_3_elemental.txt b/forge-gui/res/tokenscripts/r_3_3_elemental.txt index 0bdef3b7dbe..ec18d1cce36 100644 --- a/forge-gui/res/tokenscripts/r_3_3_elemental.txt +++ b/forge-gui/res/tokenscripts/r_3_3_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_3_fighter_first_strike.txt b/forge-gui/res/tokenscripts/r_3_3_fighter_first_strike.txt index d63fb7ef4d4..6a8163deeda 100644 --- a/forge-gui/res/tokenscripts/r_3_3_fighter_first_strike.txt +++ b/forge-gui/res/tokenscripts/r_3_3_fighter_first_strike.txt @@ -1,4 +1,4 @@ -Name:Fighter +Name:Fighter Token ManaCost:no cost Types:Creature Fighter Colors:red diff --git a/forge-gui/res/tokenscripts/r_3_3_ogre.txt b/forge-gui/res/tokenscripts/r_3_3_ogre.txt index 26c7d0d5c64..193eb191351 100644 --- a/forge-gui/res/tokenscripts/r_3_3_ogre.txt +++ b/forge-gui/res/tokenscripts/r_3_3_ogre.txt @@ -1,4 +1,4 @@ -Name:Ogre +Name:Ogre Token ManaCost:no cost Types:Creature Ogre Colors:red diff --git a/forge-gui/res/tokenscripts/r_4_4_bird_flying.txt b/forge-gui/res/tokenscripts/r_4_4_bird_flying.txt index 50fb4fc409c..15791d48eae 100644 --- a/forge-gui/res/tokenscripts/r_4_4_bird_flying.txt +++ b/forge-gui/res/tokenscripts/r_4_4_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Bird +Name:Bird Token ManaCost:no cost Types:Creature Bird Colors:red diff --git a/forge-gui/res/tokenscripts/r_4_4_devil_haste_treasure.txt b/forge-gui/res/tokenscripts/r_4_4_devil_haste_treasure.txt index 1a085e4cf5c..e98997b89f5 100644 --- a/forge-gui/res/tokenscripts/r_4_4_devil_haste_treasure.txt +++ b/forge-gui/res/tokenscripts/r_4_4_devil_haste_treasure.txt @@ -1,4 +1,4 @@ -Name:Devil +Name:Devil Token ManaCost:no cost Types:Creature Devil Colors:red diff --git a/forge-gui/res/tokenscripts/r_4_4_dragon_flying.txt b/forge-gui/res/tokenscripts/r_4_4_dragon_flying.txt index e5b42013ebd..8ba64f2b148 100644 --- a/forge-gui/res/tokenscripts/r_4_4_dragon_flying.txt +++ b/forge-gui/res/tokenscripts/r_4_4_dragon_flying.txt @@ -1,4 +1,4 @@ -Name:Dragon +Name:Dragon Token ManaCost:no cost Types:Creature Dragon Colors:red diff --git a/forge-gui/res/tokenscripts/r_4_4_giant.txt b/forge-gui/res/tokenscripts/r_4_4_giant.txt index 271091c5e60..d65318b3413 100644 --- a/forge-gui/res/tokenscripts/r_4_4_giant.txt +++ b/forge-gui/res/tokenscripts/r_4_4_giant.txt @@ -1,4 +1,4 @@ -Name:Giant +Name:Giant Token ManaCost:no cost Types:Creature Giant Colors:red diff --git a/forge-gui/res/tokenscripts/r_4_4_giant_chicken.txt b/forge-gui/res/tokenscripts/r_4_4_giant_chicken.txt index 28f4baed396..bdbc3c32b97 100644 --- a/forge-gui/res/tokenscripts/r_4_4_giant_chicken.txt +++ b/forge-gui/res/tokenscripts/r_4_4_giant_chicken.txt @@ -1,4 +1,4 @@ -Name:Giant Chicken +Name:Giant Chicken Token ManaCost:no cost Types:Creature Giant Bird Colors:red diff --git a/forge-gui/res/tokenscripts/r_4_4_hellion.txt b/forge-gui/res/tokenscripts/r_4_4_hellion.txt index 47ab6293fa3..4708bae3a40 100644 --- a/forge-gui/res/tokenscripts/r_4_4_hellion.txt +++ b/forge-gui/res/tokenscripts/r_4_4_hellion.txt @@ -1,4 +1,4 @@ -Name:Hellion +Name:Hellion Token ManaCost:no cost Types:Creature Hellion Colors:red diff --git a/forge-gui/res/tokenscripts/r_4_4_hellion_haste.txt b/forge-gui/res/tokenscripts/r_4_4_hellion_haste.txt index 0323012c597..ed57bb33765 100644 --- a/forge-gui/res/tokenscripts/r_4_4_hellion_haste.txt +++ b/forge-gui/res/tokenscripts/r_4_4_hellion_haste.txt @@ -1,4 +1,4 @@ -Name:Hellion +Name:Hellion Token ManaCost:no cost Types:Creature Hellion Colors:red diff --git a/forge-gui/res/tokenscripts/r_4_4_ogre.txt b/forge-gui/res/tokenscripts/r_4_4_ogre.txt index 12ac95a0c79..0c8c2bc20e3 100644 --- a/forge-gui/res/tokenscripts/r_4_4_ogre.txt +++ b/forge-gui/res/tokenscripts/r_4_4_ogre.txt @@ -1,4 +1,4 @@ -Name:Ogre +Name:Ogre Token ManaCost:no cost Types:Creature Ogre Colors:red diff --git a/forge-gui/res/tokenscripts/r_5_5_dragon_flying.txt b/forge-gui/res/tokenscripts/r_5_5_dragon_flying.txt index 25d2382e3ae..018dc8c7fee 100644 --- a/forge-gui/res/tokenscripts/r_5_5_dragon_flying.txt +++ b/forge-gui/res/tokenscripts/r_5_5_dragon_flying.txt @@ -1,4 +1,4 @@ -Name:Dragon +Name:Dragon Token ManaCost:no cost Types:Creature Dragon Colors:red diff --git a/forge-gui/res/tokenscripts/r_6_6_dragon_flying.txt b/forge-gui/res/tokenscripts/r_6_6_dragon_flying.txt index 4861a6550ac..1056403d90c 100644 --- a/forge-gui/res/tokenscripts/r_6_6_dragon_flying.txt +++ b/forge-gui/res/tokenscripts/r_6_6_dragon_flying.txt @@ -1,4 +1,4 @@ -Name:Dragon +Name:Dragon Token ManaCost:no cost Types:Creature Dragon Colors:red diff --git a/forge-gui/res/tokenscripts/r_7_1_elemental_trample_haste.txt b/forge-gui/res/tokenscripts/r_7_1_elemental_trample_haste.txt index bf86978720d..a6da7ade1ed 100644 --- a/forge-gui/res/tokenscripts/r_7_1_elemental_trample_haste.txt +++ b/forge-gui/res/tokenscripts/r_7_1_elemental_trample_haste.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_8_8_lizard.txt b/forge-gui/res/tokenscripts/r_8_8_lizard.txt index 3c55b63f11e..9cf77a0c70f 100644 --- a/forge-gui/res/tokenscripts/r_8_8_lizard.txt +++ b/forge-gui/res/tokenscripts/r_8_8_lizard.txt @@ -1,4 +1,4 @@ -Name:Lizard +Name:Lizard Token ManaCost:no cost Types:Creature Lizard Colors:red diff --git a/forge-gui/res/tokenscripts/r_x_1_elemental_trample_haste.txt b/forge-gui/res/tokenscripts/r_x_1_elemental_trample_haste.txt index 764a0229294..54f466f259b 100644 --- a/forge-gui/res/tokenscripts/r_x_1_elemental_trample_haste.txt +++ b/forge-gui/res/tokenscripts/r_x_1_elemental_trample_haste.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/r_x_x_dragon_illusion_flying_haste.txt b/forge-gui/res/tokenscripts/r_x_x_dragon_illusion_flying_haste.txt index 1274bd938f2..7b9d43f6518 100644 --- a/forge-gui/res/tokenscripts/r_x_x_dragon_illusion_flying_haste.txt +++ b/forge-gui/res/tokenscripts/r_x_x_dragon_illusion_flying_haste.txt @@ -1,4 +1,4 @@ -Name:Dragon Illusion +Name:Dragon Illusion Token ManaCost:no cost Types:Creature Dragon Illusion Colors:red diff --git a/forge-gui/res/tokenscripts/r_x_x_elemental.txt b/forge-gui/res/tokenscripts/r_x_x_elemental.txt index 99ba363c3d5..254778053a3 100644 --- a/forge-gui/res/tokenscripts/r_x_x_elemental.txt +++ b/forge-gui/res/tokenscripts/r_x_x_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token Colors:red ManaCost:no cost PT:*/* diff --git a/forge-gui/res/tokenscripts/r_x_x_elemental_trample_grave_exile.txt b/forge-gui/res/tokenscripts/r_x_x_elemental_trample_grave_exile.txt index bd4eb1b767a..a0ba74e5400 100644 --- a/forge-gui/res/tokenscripts/r_x_x_elemental_trample_grave_exile.txt +++ b/forge-gui/res/tokenscripts/r_x_x_elemental_trample_grave_exile.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red diff --git a/forge-gui/res/tokenscripts/rg_1_1_dragon_flying_devour.txt b/forge-gui/res/tokenscripts/rg_1_1_dragon_flying_devour.txt index 86409700d88..1b2beddae16 100644 --- a/forge-gui/res/tokenscripts/rg_1_1_dragon_flying_devour.txt +++ b/forge-gui/res/tokenscripts/rg_1_1_dragon_flying_devour.txt @@ -1,4 +1,4 @@ -Name:Dragon +Name:Dragon Token ManaCost:no cost Types:Creature Dragon Colors:red,green diff --git a/forge-gui/res/tokenscripts/rg_1_1_goblin_warrior.txt b/forge-gui/res/tokenscripts/rg_1_1_goblin_warrior.txt index 8d9c4de476f..848b3d4f1e2 100644 --- a/forge-gui/res/tokenscripts/rg_1_1_goblin_warrior.txt +++ b/forge-gui/res/tokenscripts/rg_1_1_goblin_warrior.txt @@ -1,4 +1,4 @@ -Name:Goblin Warrior +Name:Goblin Warrior Token ManaCost:no cost Types:Creature Goblin Warrior Colors:red,green diff --git a/forge-gui/res/tokenscripts/rg_2_2_satyr_haste.txt b/forge-gui/res/tokenscripts/rg_2_2_satyr_haste.txt index b4b31d81cd4..d1d24df0d32 100644 --- a/forge-gui/res/tokenscripts/rg_2_2_satyr_haste.txt +++ b/forge-gui/res/tokenscripts/rg_2_2_satyr_haste.txt @@ -1,4 +1,4 @@ -Name:Satyr +Name:Satyr Token ManaCost:no cost Types:Creature Satyr Colors:red,green diff --git a/forge-gui/res/tokenscripts/rg_4_4_beast_trample.txt b/forge-gui/res/tokenscripts/rg_4_4_beast_trample.txt index c90867901fd..abcd6f9ed64 100644 --- a/forge-gui/res/tokenscripts/rg_4_4_beast_trample.txt +++ b/forge-gui/res/tokenscripts/rg_4_4_beast_trample.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token ManaCost:no cost Types:Creature Beast Colors:red,green diff --git a/forge-gui/res/tokenscripts/rg_4_4_giant_warrior_haste.txt b/forge-gui/res/tokenscripts/rg_4_4_giant_warrior_haste.txt index 1784657ead3..25105f376d3 100644 --- a/forge-gui/res/tokenscripts/rg_4_4_giant_warrior_haste.txt +++ b/forge-gui/res/tokenscripts/rg_4_4_giant_warrior_haste.txt @@ -1,4 +1,4 @@ -Name:Giant Warrior +Name:Giant Warrior Token ManaCost:no cost Types:Creature Giant Warrior Colors:red,green diff --git a/forge-gui/res/tokenscripts/rg_5_4_dragon_spirit_damagesac.txt b/forge-gui/res/tokenscripts/rg_5_4_dragon_spirit_damagesac.txt index d2d1867d5f0..3cef63cb6a6 100644 --- a/forge-gui/res/tokenscripts/rg_5_4_dragon_spirit_damagesac.txt +++ b/forge-gui/res/tokenscripts/rg_5_4_dragon_spirit_damagesac.txt @@ -1,4 +1,4 @@ -Name:Dragon Spirit +Name:Dragon Spirit Token ManaCost:no cost Types:Creature Dragon Spirit Colors:red,green diff --git a/forge-gui/res/tokenscripts/rg_5_5_elemental.txt b/forge-gui/res/tokenscripts/rg_5_5_elemental.txt index f3f0b894eda..4512d5006a9 100644 --- a/forge-gui/res/tokenscripts/rg_5_5_elemental.txt +++ b/forge-gui/res/tokenscripts/rg_5_5_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:red,green diff --git a/forge-gui/res/tokenscripts/rgw_1_1_sand_warrior.txt b/forge-gui/res/tokenscripts/rgw_1_1_sand_warrior.txt index ab5230762ab..17530b990aa 100644 --- a/forge-gui/res/tokenscripts/rgw_1_1_sand_warrior.txt +++ b/forge-gui/res/tokenscripts/rgw_1_1_sand_warrior.txt @@ -1,4 +1,4 @@ -Name:Sand Warrior +Name:Sand Warrior Token Types:Creature Sand Warrior Colors:red,green,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/rgw_8_8_beast.txt b/forge-gui/res/tokenscripts/rgw_8_8_beast.txt index 7f4a99db68e..eedb43bef5e 100644 --- a/forge-gui/res/tokenscripts/rgw_8_8_beast.txt +++ b/forge-gui/res/tokenscripts/rgw_8_8_beast.txt @@ -1,4 +1,4 @@ -Name:Beast +Name:Beast Token Types:Creature Beast Colors:red,green,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/riptide_replicator.txt b/forge-gui/res/tokenscripts/riptide_replicator.txt index 2e79845d026..e17ece439c8 100644 --- a/forge-gui/res/tokenscripts/riptide_replicator.txt +++ b/forge-gui/res/tokenscripts/riptide_replicator.txt @@ -1,4 +1,4 @@ -Name:ChosenType +Name:ChosenType Token ManaCost:no cost Types:Creature PT:*/* diff --git a/forge-gui/res/tokenscripts/rw_1_1_goblin_soldier.txt b/forge-gui/res/tokenscripts/rw_1_1_goblin_soldier.txt index 4686e3489b9..64d8b1e81ce 100644 --- a/forge-gui/res/tokenscripts/rw_1_1_goblin_soldier.txt +++ b/forge-gui/res/tokenscripts/rw_1_1_goblin_soldier.txt @@ -1,4 +1,4 @@ -Name:Goblin Soldier +Name:Goblin Soldier Token Types:Creature Goblin Soldier Colors:red,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/rw_1_1_soldier_haste.txt b/forge-gui/res/tokenscripts/rw_1_1_soldier_haste.txt index e063344c3fe..30abfd1b23a 100644 --- a/forge-gui/res/tokenscripts/rw_1_1_soldier_haste.txt +++ b/forge-gui/res/tokenscripts/rw_1_1_soldier_haste.txt @@ -1,4 +1,4 @@ -Name:Soldier +Name:Soldier Token Types:Creature Soldier Colors:red,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/rw_1_2_human_rogue_haste_damage.txt b/forge-gui/res/tokenscripts/rw_1_2_human_rogue_haste_damage.txt index 140f40734c7..f3de5943dbe 100644 --- a/forge-gui/res/tokenscripts/rw_1_2_human_rogue_haste_damage.txt +++ b/forge-gui/res/tokenscripts/rw_1_2_human_rogue_haste_damage.txt @@ -1,4 +1,4 @@ -Name:Human Rogue +Name:Human Rogue Token Types:Creature Human Rogue Colors:red,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/rw_2_1_human_cleric_lifelink_haste.txt b/forge-gui/res/tokenscripts/rw_2_1_human_cleric_lifelink_haste.txt index eb192d3f740..20c48cd3868 100644 --- a/forge-gui/res/tokenscripts/rw_2_1_human_cleric_lifelink_haste.txt +++ b/forge-gui/res/tokenscripts/rw_2_1_human_cleric_lifelink_haste.txt @@ -1,4 +1,4 @@ -Name:Human Cleric +Name:Human Cleric Token Types:Creature Human Cleric Colors:red,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/rw_2_2_dinosaur_cat.txt b/forge-gui/res/tokenscripts/rw_2_2_dinosaur_cat.txt index 42b41dbf15b..71d63dd89a1 100644 --- a/forge-gui/res/tokenscripts/rw_2_2_dinosaur_cat.txt +++ b/forge-gui/res/tokenscripts/rw_2_2_dinosaur_cat.txt @@ -1,4 +1,4 @@ -Name:Dinosaur Cat +Name:Dinosaur Cat Token Types:Creature Dinosaur Cat Colors:red,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/rw_3_1_human_warrior_trample_haste.txt b/forge-gui/res/tokenscripts/rw_3_1_human_warrior_trample_haste.txt index 3c0b16a0c46..112caf29dbf 100644 --- a/forge-gui/res/tokenscripts/rw_3_1_human_warrior_trample_haste.txt +++ b/forge-gui/res/tokenscripts/rw_3_1_human_warrior_trample_haste.txt @@ -1,4 +1,4 @@ -Name:Human Warrior +Name:Human Warrior Token Types:Creature Human Warrior Colors:red,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/rw_3_2_spirit.txt b/forge-gui/res/tokenscripts/rw_3_2_spirit.txt index 605a8f80551..944db0d3519 100644 --- a/forge-gui/res/tokenscripts/rw_3_2_spirit.txt +++ b/forge-gui/res/tokenscripts/rw_3_2_spirit.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token Types:Creature Spirit Colors:red,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/rw_4_4_a_golem.txt b/forge-gui/res/tokenscripts/rw_4_4_a_golem.txt index 94ff4dc94cc..7c07cb5b242 100644 --- a/forge-gui/res/tokenscripts/rw_4_4_a_golem.txt +++ b/forge-gui/res/tokenscripts/rw_4_4_a_golem.txt @@ -1,4 +1,4 @@ -Name:Golem +Name:Golem Token Types:Artifact Creature Golem Colors:red,white ManaCost:no cost diff --git a/forge-gui/res/tokenscripts/u_0_1_a_homunculus.txt b/forge-gui/res/tokenscripts/u_0_1_a_homunculus.txt index 6284058aab4..b974c2e39c0 100644 --- a/forge-gui/res/tokenscripts/u_0_1_a_homunculus.txt +++ b/forge-gui/res/tokenscripts/u_0_1_a_homunculus.txt @@ -1,4 +1,4 @@ -Name:Homunculus +Name:Homunculus Token ManaCost:no cost Types:Artifact Creature Homunculus Colors:blue diff --git a/forge-gui/res/tokenscripts/u_0_1_starfish.txt b/forge-gui/res/tokenscripts/u_0_1_starfish.txt index 6d01b6fc71c..8b5e1ce6086 100644 --- a/forge-gui/res/tokenscripts/u_0_1_starfish.txt +++ b/forge-gui/res/tokenscripts/u_0_1_starfish.txt @@ -1,4 +1,4 @@ -Name:Starfish +Name:Starfish Token ManaCost:no cost Types:Creature Starfish Colors:blue diff --git a/forge-gui/res/tokenscripts/u_0_2_illusion_mesmerize.txt b/forge-gui/res/tokenscripts/u_0_2_illusion_mesmerize.txt index 1f1d57e0e2f..80f2caf8d0f 100644 --- a/forge-gui/res/tokenscripts/u_0_2_illusion_mesmerize.txt +++ b/forge-gui/res/tokenscripts/u_0_2_illusion_mesmerize.txt @@ -1,4 +1,4 @@ -Name:Illusion +Name:Illusion Token Types:Creature Illusion ManaCost:no cost Colors:blue diff --git a/forge-gui/res/tokenscripts/u_0_3_crab.txt b/forge-gui/res/tokenscripts/u_0_3_crab.txt index a15f26e4364..92d930bf152 100644 --- a/forge-gui/res/tokenscripts/u_0_3_crab.txt +++ b/forge-gui/res/tokenscripts/u_0_3_crab.txt @@ -1,4 +1,4 @@ -Name:Crab +Name:Crab Token ManaCost:no cost Types:Creature Crab Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_0_elemental.txt b/forge-gui/res/tokenscripts/u_1_0_elemental.txt index 13e30a3e7e0..711aa04717f 100644 --- a/forge-gui/res/tokenscripts/u_1_0_elemental.txt +++ b/forge-gui/res/tokenscripts/u_1_0_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_a_thopter_flying.txt b/forge-gui/res/tokenscripts/u_1_1_a_thopter_flying.txt index ec591279dc1..ac04afb21a4 100644 --- a/forge-gui/res/tokenscripts/u_1_1_a_thopter_flying.txt +++ b/forge-gui/res/tokenscripts/u_1_1_a_thopter_flying.txt @@ -1,4 +1,4 @@ -Name:Thopter +Name:Thopter Token ManaCost:no cost Types:Artifact Creature Thopter Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_beeble.txt b/forge-gui/res/tokenscripts/u_1_1_beeble.txt index 195e1436abe..99dfaeffc60 100644 --- a/forge-gui/res/tokenscripts/u_1_1_beeble.txt +++ b/forge-gui/res/tokenscripts/u_1_1_beeble.txt @@ -1,4 +1,4 @@ -Name:Beeble +Name:Beeble Token ManaCost:no cost Types:Creature Beeble Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_bird_flying.txt b/forge-gui/res/tokenscripts/u_1_1_bird_flying.txt index 72cbe166983..d0370a5c0a5 100644 --- a/forge-gui/res/tokenscripts/u_1_1_bird_flying.txt +++ b/forge-gui/res/tokenscripts/u_1_1_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Bird +Name:Bird Token ManaCost:no cost Types:Creature Bird Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_bird_flying_blockflying.txt b/forge-gui/res/tokenscripts/u_1_1_bird_flying_blockflying.txt index abfebbbacb6..3b49b219e2d 100644 --- a/forge-gui/res/tokenscripts/u_1_1_bird_flying_blockflying.txt +++ b/forge-gui/res/tokenscripts/u_1_1_bird_flying_blockflying.txt @@ -1,4 +1,4 @@ -Name:Bird +Name:Bird Token ManaCost:no cost Types:Creature Bird Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_bird_illusion_flying.txt b/forge-gui/res/tokenscripts/u_1_1_bird_illusion_flying.txt index c9a001ee43c..a08717b1a14 100644 --- a/forge-gui/res/tokenscripts/u_1_1_bird_illusion_flying.txt +++ b/forge-gui/res/tokenscripts/u_1_1_bird_illusion_flying.txt @@ -1,4 +1,4 @@ -Name:Bird Illusion +Name:Bird Illusion Token ManaCost:no cost Types:Creature Bird Illusion Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_camarid.txt b/forge-gui/res/tokenscripts/u_1_1_camarid.txt index 71b54ee7e23..648e48664fe 100644 --- a/forge-gui/res/tokenscripts/u_1_1_camarid.txt +++ b/forge-gui/res/tokenscripts/u_1_1_camarid.txt @@ -1,4 +1,4 @@ -Name:Camarid +Name:Camarid Token ManaCost:no cost Types:Creature Camarid Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_faerie_dragon_flying.txt b/forge-gui/res/tokenscripts/u_1_1_faerie_dragon_flying.txt index 23f14a9f4ea..ed034dd0fbd 100644 --- a/forge-gui/res/tokenscripts/u_1_1_faerie_dragon_flying.txt +++ b/forge-gui/res/tokenscripts/u_1_1_faerie_dragon_flying.txt @@ -1,4 +1,4 @@ -Name:Faerie Dragon +Name:Faerie Dragon Token ManaCost:no cost Types:Creature Faerie Dragon Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_faerie_flying.txt b/forge-gui/res/tokenscripts/u_1_1_faerie_flying.txt index 54d1ed9ef06..29ade6ebf3a 100644 --- a/forge-gui/res/tokenscripts/u_1_1_faerie_flying.txt +++ b/forge-gui/res/tokenscripts/u_1_1_faerie_flying.txt @@ -1,4 +1,4 @@ -Name:Faerie +Name:Faerie Token ManaCost:no cost Types:Creature Faerie Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_faerie_spy_flying_haste_draw.txt b/forge-gui/res/tokenscripts/u_1_1_faerie_spy_flying_haste_draw.txt index 18bb6f9ea39..5ee37dc1753 100644 --- a/forge-gui/res/tokenscripts/u_1_1_faerie_spy_flying_haste_draw.txt +++ b/forge-gui/res/tokenscripts/u_1_1_faerie_spy_flying_haste_draw.txt @@ -1,4 +1,4 @@ -Name:Faerie +Name:Faerie Token ManaCost:no cost Types:Creature Faerie Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_human_wizard.txt b/forge-gui/res/tokenscripts/u_1_1_human_wizard.txt index c7cc08b194e..0d05fd1620f 100644 --- a/forge-gui/res/tokenscripts/u_1_1_human_wizard.txt +++ b/forge-gui/res/tokenscripts/u_1_1_human_wizard.txt @@ -1,4 +1,4 @@ -Name:Human Wizard +Name:Human Wizard Token ManaCost:no cost Types:Creature Human Wizard Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_illusion_flying.txt b/forge-gui/res/tokenscripts/u_1_1_illusion_flying.txt index 52271b2d7c7..1d86fc62289 100644 --- a/forge-gui/res/tokenscripts/u_1_1_illusion_flying.txt +++ b/forge-gui/res/tokenscripts/u_1_1_illusion_flying.txt @@ -1,4 +1,4 @@ -Name:Illusion +Name:Illusion Token ManaCost:no cost Types:Creature Illusion Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_illusion_other_illusions.txt b/forge-gui/res/tokenscripts/u_1_1_illusion_other_illusions.txt index 058300289ea..5cf98a34e15 100644 --- a/forge-gui/res/tokenscripts/u_1_1_illusion_other_illusions.txt +++ b/forge-gui/res/tokenscripts/u_1_1_illusion_other_illusions.txt @@ -1,4 +1,4 @@ -Name:Illusion +Name:Illusion Token ManaCost:no cost Types:Creature Illusion Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_merfolk.txt b/forge-gui/res/tokenscripts/u_1_1_merfolk.txt index a0ec07b2384..bc9724430f3 100644 --- a/forge-gui/res/tokenscripts/u_1_1_merfolk.txt +++ b/forge-gui/res/tokenscripts/u_1_1_merfolk.txt @@ -1,4 +1,4 @@ -Name:Merfolk +Name:Merfolk Token ManaCost:no cost Types:Creature Merfolk Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_merfolk_hexproof.txt b/forge-gui/res/tokenscripts/u_1_1_merfolk_hexproof.txt index ed058cf208c..95a2b314af9 100644 --- a/forge-gui/res/tokenscripts/u_1_1_merfolk_hexproof.txt +++ b/forge-gui/res/tokenscripts/u_1_1_merfolk_hexproof.txt @@ -1,4 +1,4 @@ -Name:Merfolk +Name:Merfolk Token ManaCost:no cost Types:Creature Merfolk Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_merfolk_wizard.txt b/forge-gui/res/tokenscripts/u_1_1_merfolk_wizard.txt index 4f1624f40f9..44f629d64bb 100644 --- a/forge-gui/res/tokenscripts/u_1_1_merfolk_wizard.txt +++ b/forge-gui/res/tokenscripts/u_1_1_merfolk_wizard.txt @@ -1,4 +1,4 @@ -Name:Merfolk Wizard +Name:Merfolk Wizard Token ManaCost:no cost Types:Creature Merfolk Wizard Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_spirit_flying.txt b/forge-gui/res/tokenscripts/u_1_1_spirit_flying.txt index cab4a9c095a..bdc4a1bc66a 100644 --- a/forge-gui/res/tokenscripts/u_1_1_spirit_flying.txt +++ b/forge-gui/res/tokenscripts/u_1_1_spirit_flying.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Creature Spirit Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_squid_islandwalk.txt b/forge-gui/res/tokenscripts/u_1_1_squid_islandwalk.txt index 035c3e499c7..2a04753219e 100644 --- a/forge-gui/res/tokenscripts/u_1_1_squid_islandwalk.txt +++ b/forge-gui/res/tokenscripts/u_1_1_squid_islandwalk.txt @@ -1,4 +1,4 @@ -Name:Squid +Name:Squid Token ManaCost:no cost Types:Creature Squid Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_tentacle.txt b/forge-gui/res/tokenscripts/u_1_1_tentacle.txt index 690dd81f5fc..8ad3b9e47c9 100644 --- a/forge-gui/res/tokenscripts/u_1_1_tentacle.txt +++ b/forge-gui/res/tokenscripts/u_1_1_tentacle.txt @@ -1,4 +1,4 @@ -Name:Tentacle +Name:Tentacle Token ManaCost:no cost Types:Creature Tentacle Colors:blue diff --git a/forge-gui/res/tokenscripts/u_1_1_wizard_flying.txt b/forge-gui/res/tokenscripts/u_1_1_wizard_flying.txt index c20298e7050..af243524c1e 100644 --- a/forge-gui/res/tokenscripts/u_1_1_wizard_flying.txt +++ b/forge-gui/res/tokenscripts/u_1_1_wizard_flying.txt @@ -1,4 +1,4 @@ -Name:Wizard +Name:Wizard Token ManaCost:no cost Types:Creature Wizard Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_1_a_phyrexian_myr.txt b/forge-gui/res/tokenscripts/u_2_1_a_phyrexian_myr.txt index b8197fe2341..5e9c0bbc9d1 100644 --- a/forge-gui/res/tokenscripts/u_2_1_a_phyrexian_myr.txt +++ b/forge-gui/res/tokenscripts/u_2_1_a_phyrexian_myr.txt @@ -1,4 +1,4 @@ -Name:Phyrexian Myr +Name:Phyrexian Myr Token ManaCost:no cost Types:Artifact Creature Phyrexian Myr Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_2_bird_flying.txt b/forge-gui/res/tokenscripts/u_2_2_bird_flying.txt index b470ea0aac4..1eb6e824437 100644 --- a/forge-gui/res/tokenscripts/u_2_2_bird_flying.txt +++ b/forge-gui/res/tokenscripts/u_2_2_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Bird +Name:Bird Token ManaCost:no cost Types:Creature Bird Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_2_djinn_monk_flying.txt b/forge-gui/res/tokenscripts/u_2_2_djinn_monk_flying.txt index 8cae7751c5e..8dde331ea8a 100644 --- a/forge-gui/res/tokenscripts/u_2_2_djinn_monk_flying.txt +++ b/forge-gui/res/tokenscripts/u_2_2_djinn_monk_flying.txt @@ -1,4 +1,4 @@ -Name:Djinn Monk +Name:Djinn Monk Token ManaCost:no cost Types:Creature Djinn Monk Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_2_drake_flying.txt b/forge-gui/res/tokenscripts/u_2_2_drake_flying.txt index 386f92206ef..faa49a1fb8a 100644 --- a/forge-gui/res/tokenscripts/u_2_2_drake_flying.txt +++ b/forge-gui/res/tokenscripts/u_2_2_drake_flying.txt @@ -1,4 +1,4 @@ -Name:Drake +Name:Drake Token ManaCost:no cost Types:Creature Drake Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_2_e_bird_flying.txt b/forge-gui/res/tokenscripts/u_2_2_e_bird_flying.txt index 549aadacb6f..d88fc2f14b7 100644 --- a/forge-gui/res/tokenscripts/u_2_2_e_bird_flying.txt +++ b/forge-gui/res/tokenscripts/u_2_2_e_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Bird +Name:Bird Token ManaCost:no cost Types:Enchantment Creature Bird Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_2_elemental_flying.txt b/forge-gui/res/tokenscripts/u_2_2_elemental_flying.txt index f137b175704..fecd80f0548 100644 --- a/forge-gui/res/tokenscripts/u_2_2_elemental_flying.txt +++ b/forge-gui/res/tokenscripts/u_2_2_elemental_flying.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_2_homunculus.txt b/forge-gui/res/tokenscripts/u_2_2_homunculus.txt index 98fe7c4e79e..2dc10401619 100644 --- a/forge-gui/res/tokenscripts/u_2_2_homunculus.txt +++ b/forge-gui/res/tokenscripts/u_2_2_homunculus.txt @@ -1,4 +1,4 @@ -Name:Homunculus +Name:Homunculus Token ManaCost:no cost Types:Creature Homunculus Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_2_illusion.txt b/forge-gui/res/tokenscripts/u_2_2_illusion.txt index 5310390b072..d611d38e460 100644 --- a/forge-gui/res/tokenscripts/u_2_2_illusion.txt +++ b/forge-gui/res/tokenscripts/u_2_2_illusion.txt @@ -1,4 +1,4 @@ -Name:Illusion +Name:Illusion Token ManaCost:no cost Types:Creature Illusion Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_2_illusion_illusory.txt b/forge-gui/res/tokenscripts/u_2_2_illusion_illusory.txt index 9c61f20b0fd..4a44367534a 100644 --- a/forge-gui/res/tokenscripts/u_2_2_illusion_illusory.txt +++ b/forge-gui/res/tokenscripts/u_2_2_illusion_illusory.txt @@ -1,4 +1,4 @@ -Name:Illusion +Name:Illusion Token ManaCost:no cost Types:Creature Illusion Colors:blue diff --git a/forge-gui/res/tokenscripts/u_2_2_shapeshifter_changeling.txt b/forge-gui/res/tokenscripts/u_2_2_shapeshifter_changeling.txt index 7369d95ef36..be44166589a 100644 --- a/forge-gui/res/tokenscripts/u_2_2_shapeshifter_changeling.txt +++ b/forge-gui/res/tokenscripts/u_2_2_shapeshifter_changeling.txt @@ -1,4 +1,4 @@ -Name:Shapeshifter +Name:Shapeshifter Token Colors:blue ManaCost:no cost Types:Creature Shapeshifter diff --git a/forge-gui/res/tokenscripts/u_2_2_wizard.txt b/forge-gui/res/tokenscripts/u_2_2_wizard.txt index df2a7a29b3c..c84e0a38dbc 100644 --- a/forge-gui/res/tokenscripts/u_2_2_wizard.txt +++ b/forge-gui/res/tokenscripts/u_2_2_wizard.txt @@ -1,4 +1,4 @@ -Name:Wizard +Name:Wizard Token ManaCost:no cost Types:Creature Wizard Colors:blue diff --git a/forge-gui/res/tokenscripts/u_3_2_reflection.txt b/forge-gui/res/tokenscripts/u_3_2_reflection.txt index f74176c5d87..37fa03ca599 100644 --- a/forge-gui/res/tokenscripts/u_3_2_reflection.txt +++ b/forge-gui/res/tokenscripts/u_3_2_reflection.txt @@ -1,4 +1,4 @@ -Name:Reflection +Name:Reflection Token ManaCost:no cost Types:Creature Reflection Colors:blue diff --git a/forge-gui/res/tokenscripts/u_3_3_fish_hatches_whale.txt b/forge-gui/res/tokenscripts/u_3_3_fish_hatches_whale.txt index d6d1d78aa2a..9fd2cfc76ef 100644 --- a/forge-gui/res/tokenscripts/u_3_3_fish_hatches_whale.txt +++ b/forge-gui/res/tokenscripts/u_3_3_fish_hatches_whale.txt @@ -1,4 +1,4 @@ -Name:Fish +Name:Fish Token ManaCost:no cost Types:Creature Fish Colors:blue diff --git a/forge-gui/res/tokenscripts/u_3_3_weird_defender_flying.txt b/forge-gui/res/tokenscripts/u_3_3_weird_defender_flying.txt index ceb684b011f..7cb90fda618 100644 --- a/forge-gui/res/tokenscripts/u_3_3_weird_defender_flying.txt +++ b/forge-gui/res/tokenscripts/u_3_3_weird_defender_flying.txt @@ -1,4 +1,4 @@ -Name:Weird +Name:Weird Token ManaCost:no cost Types:Creature Weird Colors:blue diff --git a/forge-gui/res/tokenscripts/u_4_3_salamander_warrior.txt b/forge-gui/res/tokenscripts/u_4_3_salamander_warrior.txt index df0586f6a6d..96686504f6b 100644 --- a/forge-gui/res/tokenscripts/u_4_3_salamander_warrior.txt +++ b/forge-gui/res/tokenscripts/u_4_3_salamander_warrior.txt @@ -1,4 +1,4 @@ -Name:Salamander Warrior +Name:Salamander Warrior Token ManaCost:no cost Types:Creature Salamander Warrior Colors:blue diff --git a/forge-gui/res/tokenscripts/u_4_4_elemental_bird_flying.txt b/forge-gui/res/tokenscripts/u_4_4_elemental_bird_flying.txt index ddfbeb71a2c..f196cf35ff7 100644 --- a/forge-gui/res/tokenscripts/u_4_4_elemental_bird_flying.txt +++ b/forge-gui/res/tokenscripts/u_4_4_elemental_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Elemental Bird +Name:Elemental Bird Token ManaCost:no cost Types:Creature Elemental Bird Colors:blue diff --git a/forge-gui/res/tokenscripts/u_4_4_giant_wizard.txt b/forge-gui/res/tokenscripts/u_4_4_giant_wizard.txt index 219d9f9fab0..703d80adc27 100644 --- a/forge-gui/res/tokenscripts/u_4_4_giant_wizard.txt +++ b/forge-gui/res/tokenscripts/u_4_4_giant_wizard.txt @@ -1,4 +1,4 @@ -Name:Giant Wizard +Name:Giant Wizard Token ManaCost:no cost Types:Creature Giant Wizard Colors:blue diff --git a/forge-gui/res/tokenscripts/u_4_4_sphinx_flying.txt b/forge-gui/res/tokenscripts/u_4_4_sphinx_flying.txt index fa05c65f2bc..404ccf870fb 100644 --- a/forge-gui/res/tokenscripts/u_4_4_sphinx_flying.txt +++ b/forge-gui/res/tokenscripts/u_4_4_sphinx_flying.txt @@ -1,4 +1,4 @@ -Name:Sphinx +Name:Sphinx Token ManaCost:no cost Types:Creature Sphinx Colors:blue diff --git a/forge-gui/res/tokenscripts/u_5_5_dragon_spirit_flying.txt b/forge-gui/res/tokenscripts/u_5_5_dragon_spirit_flying.txt index c0637373e76..d263f07eeb7 100644 --- a/forge-gui/res/tokenscripts/u_5_5_dragon_spirit_flying.txt +++ b/forge-gui/res/tokenscripts/u_5_5_dragon_spirit_flying.txt @@ -1,4 +1,4 @@ -Name:Dragon Spirit +Name:Dragon Spirit Token ManaCost:no cost Types:Creature Dragon Spirit Colors:blue diff --git a/forge-gui/res/tokenscripts/u_5_5_wall_defender.txt b/forge-gui/res/tokenscripts/u_5_5_wall_defender.txt index e76e401c5bc..a8c0851fcd8 100644 --- a/forge-gui/res/tokenscripts/u_5_5_wall_defender.txt +++ b/forge-gui/res/tokenscripts/u_5_5_wall_defender.txt @@ -1,4 +1,4 @@ -Name:Wall +Name:Wall Token ManaCost:no cost Types:Creature Wall Colors:blue diff --git a/forge-gui/res/tokenscripts/u_6_6_whale_hatches_kraken.txt b/forge-gui/res/tokenscripts/u_6_6_whale_hatches_kraken.txt index ab986bd4273..97d391f0b15 100644 --- a/forge-gui/res/tokenscripts/u_6_6_whale_hatches_kraken.txt +++ b/forge-gui/res/tokenscripts/u_6_6_whale_hatches_kraken.txt @@ -1,4 +1,4 @@ -Name:Whale +Name:Whale Token ManaCost:no cost Types:Creature Whale Colors:blue diff --git a/forge-gui/res/tokenscripts/u_8_8_kraken.txt b/forge-gui/res/tokenscripts/u_8_8_kraken.txt index 96388e28772..10763964059 100644 --- a/forge-gui/res/tokenscripts/u_8_8_kraken.txt +++ b/forge-gui/res/tokenscripts/u_8_8_kraken.txt @@ -1,4 +1,4 @@ -Name:Kraken +Name:Kraken Token ManaCost:no cost Types:Creature Kraken Colors:blue diff --git a/forge-gui/res/tokenscripts/u_8_8_kraken_hexproof.txt b/forge-gui/res/tokenscripts/u_8_8_kraken_hexproof.txt index 51714b06228..eea51dead60 100644 --- a/forge-gui/res/tokenscripts/u_8_8_kraken_hexproof.txt +++ b/forge-gui/res/tokenscripts/u_8_8_kraken_hexproof.txt @@ -1,4 +1,4 @@ -Name:Kraken +Name:Kraken Token ManaCost:no cost Types:Creature Kraken Colors:blue diff --git a/forge-gui/res/tokenscripts/u_8_8_octopus.txt b/forge-gui/res/tokenscripts/u_8_8_octopus.txt index db072638def..f0271827a2b 100644 --- a/forge-gui/res/tokenscripts/u_8_8_octopus.txt +++ b/forge-gui/res/tokenscripts/u_8_8_octopus.txt @@ -1,4 +1,4 @@ -Name:Octopus +Name:Octopus Token ManaCost:no cost Types:Creature Octopus Colors:blue diff --git a/forge-gui/res/tokenscripts/u_9_9_kraken.txt b/forge-gui/res/tokenscripts/u_9_9_kraken.txt index e824b538c68..3d21db33684 100644 --- a/forge-gui/res/tokenscripts/u_9_9_kraken.txt +++ b/forge-gui/res/tokenscripts/u_9_9_kraken.txt @@ -1,4 +1,4 @@ -Name:Kraken +Name:Kraken Token ManaCost:no cost Types:Creature Kraken Colors:blue diff --git a/forge-gui/res/tokenscripts/u_x_x_dog_illusion_cardsinhand.txt b/forge-gui/res/tokenscripts/u_x_x_dog_illusion_cardsinhand.txt index 89cf60ded0f..039b41993f8 100644 --- a/forge-gui/res/tokenscripts/u_x_x_dog_illusion_cardsinhand.txt +++ b/forge-gui/res/tokenscripts/u_x_x_dog_illusion_cardsinhand.txt @@ -1,4 +1,4 @@ -Name:Dog Illusion +Name:Dog Illusion Token ManaCost:no cost Types:Creature Dog Illusion Colors:blue diff --git a/forge-gui/res/tokenscripts/u_x_x_illusion.txt b/forge-gui/res/tokenscripts/u_x_x_illusion.txt index 13bb19d2953..b3ef8c1cf1c 100644 --- a/forge-gui/res/tokenscripts/u_x_x_illusion.txt +++ b/forge-gui/res/tokenscripts/u_x_x_illusion.txt @@ -1,4 +1,4 @@ -Name:Illusion +Name:Illusion Token ManaCost:no cost Types:Creature Illusion Colors:blue diff --git a/forge-gui/res/tokenscripts/u_x_x_orb_flying.txt b/forge-gui/res/tokenscripts/u_x_x_orb_flying.txt index b1b2b9fdc9e..15e0b6cf47e 100644 --- a/forge-gui/res/tokenscripts/u_x_x_orb_flying.txt +++ b/forge-gui/res/tokenscripts/u_x_x_orb_flying.txt @@ -1,4 +1,4 @@ -Name:Orb +Name:Orb Token ManaCost:no cost Types:Creature Orb Colors:blue diff --git a/forge-gui/res/tokenscripts/u_x_x_shark_flying.txt b/forge-gui/res/tokenscripts/u_x_x_shark_flying.txt index 8da980b6426..2887c478d75 100644 --- a/forge-gui/res/tokenscripts/u_x_x_shark_flying.txt +++ b/forge-gui/res/tokenscripts/u_x_x_shark_flying.txt @@ -1,4 +1,4 @@ -Name:Shark +Name:Shark Token ManaCost:no cost Types:Creature Shark Colors:blue diff --git a/forge-gui/res/tokenscripts/u_x_x_zombie.txt b/forge-gui/res/tokenscripts/u_x_x_zombie.txt index 638c56e6e0b..c1e95a0428c 100644 --- a/forge-gui/res/tokenscripts/u_x_x_zombie.txt +++ b/forge-gui/res/tokenscripts/u_x_x_zombie.txt @@ -1,4 +1,4 @@ -Name:Zombie +Name:Zombie Token ManaCost:no cost Types:Creature Zombie Colors:blue diff --git a/forge-gui/res/tokenscripts/ub_1_1_faerie_rogue_flying.txt b/forge-gui/res/tokenscripts/ub_1_1_faerie_rogue_flying.txt index 9d102dc7d7b..43164abab74 100644 --- a/forge-gui/res/tokenscripts/ub_1_1_faerie_rogue_flying.txt +++ b/forge-gui/res/tokenscripts/ub_1_1_faerie_rogue_flying.txt @@ -1,4 +1,4 @@ -Name:Faerie Rogue +Name:Faerie Rogue Token ManaCost:no cost Types:Creature Faerie Rogue Colors:blue,black diff --git a/forge-gui/res/tokenscripts/ub_1_1_horror_flying.txt b/forge-gui/res/tokenscripts/ub_1_1_horror_flying.txt index 4056d87c918..355357d49d3 100644 --- a/forge-gui/res/tokenscripts/ub_1_1_horror_flying.txt +++ b/forge-gui/res/tokenscripts/ub_1_1_horror_flying.txt @@ -1,4 +1,4 @@ -Name:Horror +Name:Horror Token ManaCost:no cost Types:Creature Horror Colors:blue,black diff --git a/forge-gui/res/tokenscripts/ub_1_1_zombie_wizard.txt b/forge-gui/res/tokenscripts/ub_1_1_zombie_wizard.txt index 5b47e98a4e9..5b534fdab3d 100644 --- a/forge-gui/res/tokenscripts/ub_1_1_zombie_wizard.txt +++ b/forge-gui/res/tokenscripts/ub_1_1_zombie_wizard.txt @@ -1,4 +1,4 @@ -Name:Zombie Wizard +Name:Zombie Wizard Token ManaCost:no cost Types:Creature Zombie Wizard Colors:blue,black diff --git a/forge-gui/res/tokenscripts/ub_2_3_nightmare_mill.txt b/forge-gui/res/tokenscripts/ub_2_3_nightmare_mill.txt index 4859aaf4a7a..74fd1d5bcb2 100644 --- a/forge-gui/res/tokenscripts/ub_2_3_nightmare_mill.txt +++ b/forge-gui/res/tokenscripts/ub_2_3_nightmare_mill.txt @@ -1,4 +1,4 @@ -Name:Nightmare +Name:Nightmare Token ManaCost:no cost Types:Creature Nightmare Colors:blue,black diff --git a/forge-gui/res/tokenscripts/ub_x_x_zombie_menace.txt b/forge-gui/res/tokenscripts/ub_x_x_zombie_menace.txt index 54ef7eb410f..1c678377f69 100644 --- a/forge-gui/res/tokenscripts/ub_x_x_zombie_menace.txt +++ b/forge-gui/res/tokenscripts/ub_x_x_zombie_menace.txt @@ -1,4 +1,4 @@ -Name:Zombie +Name:Zombie Token ManaCost:no cost Types:Creature Zombie Colors:blue,black diff --git a/forge-gui/res/tokenscripts/ur_1_1_insect_flying_haste.txt b/forge-gui/res/tokenscripts/ur_1_1_insect_flying_haste.txt index c369d70ae5e..a1d233924ce 100644 --- a/forge-gui/res/tokenscripts/ur_1_1_insect_flying_haste.txt +++ b/forge-gui/res/tokenscripts/ur_1_1_insect_flying_haste.txt @@ -1,4 +1,4 @@ -Name:Insect +Name:Insect Token ManaCost:no cost Types:Creature Insect Colors:blue,red diff --git a/forge-gui/res/tokenscripts/ur_4_4_elemental.txt b/forge-gui/res/tokenscripts/ur_4_4_elemental.txt index 9eaa688a803..01654ef954c 100644 --- a/forge-gui/res/tokenscripts/ur_4_4_elemental.txt +++ b/forge-gui/res/tokenscripts/ur_4_4_elemental.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Colors:blue,red Types:Creature Elemental diff --git a/forge-gui/res/tokenscripts/ur_5_5_elemental_flying.txt b/forge-gui/res/tokenscripts/ur_5_5_elemental_flying.txt index dbbe1aa69b2..42a59815767 100644 --- a/forge-gui/res/tokenscripts/ur_5_5_elemental_flying.txt +++ b/forge-gui/res/tokenscripts/ur_5_5_elemental_flying.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:blue,red diff --git a/forge-gui/res/tokenscripts/ur_x_x_weird.txt b/forge-gui/res/tokenscripts/ur_x_x_weird.txt index 22a2cd5dd7b..d9e4ad756b8 100644 --- a/forge-gui/res/tokenscripts/ur_x_x_weird.txt +++ b/forge-gui/res/tokenscripts/ur_x_x_weird.txt @@ -1,4 +1,4 @@ -Name:Weird +Name:Weird Token ManaCost:no cost Types:Creature Weird Colors:blue,red diff --git a/forge-gui/res/tokenscripts/volraths_laboratory.txt b/forge-gui/res/tokenscripts/volraths_laboratory.txt index ad251755769..4e5332ff41d 100644 --- a/forge-gui/res/tokenscripts/volraths_laboratory.txt +++ b/forge-gui/res/tokenscripts/volraths_laboratory.txt @@ -1,4 +1,4 @@ -Name:ChosenType +Name:ChosenType Token ManaCost:no cost Types:Creature PT:2/2 diff --git a/forge-gui/res/tokenscripts/w_0_0_spirit_flying.txt b/forge-gui/res/tokenscripts/w_0_0_spirit_flying.txt index 9135eadc2c1..4e94d561eed 100644 --- a/forge-gui/res/tokenscripts/w_0_0_spirit_flying.txt +++ b/forge-gui/res/tokenscripts/w_0_0_spirit_flying.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Creature Spirit Colors:white diff --git a/forge-gui/res/tokenscripts/w_0_1_caribou.txt b/forge-gui/res/tokenscripts/w_0_1_caribou.txt index 69cd9dafa8d..cb2878d50ed 100644 --- a/forge-gui/res/tokenscripts/w_0_1_caribou.txt +++ b/forge-gui/res/tokenscripts/w_0_1_caribou.txt @@ -1,4 +1,4 @@ -Name:Caribou +Name:Caribou Token ManaCost:no cost Types:Creature Caribou Colors:white diff --git a/forge-gui/res/tokenscripts/w_0_1_deserter.txt b/forge-gui/res/tokenscripts/w_0_1_deserter.txt index eae53eb035c..465535d9710 100644 --- a/forge-gui/res/tokenscripts/w_0_1_deserter.txt +++ b/forge-gui/res/tokenscripts/w_0_1_deserter.txt @@ -1,4 +1,4 @@ -Name:Deserter +Name:Deserter Token ManaCost:no cost Types:Creature Deserter Colors:white diff --git a/forge-gui/res/tokenscripts/w_0_1_goat.txt b/forge-gui/res/tokenscripts/w_0_1_goat.txt index f9f833a65cb..fbc30c27614 100644 --- a/forge-gui/res/tokenscripts/w_0_1_goat.txt +++ b/forge-gui/res/tokenscripts/w_0_1_goat.txt @@ -1,4 +1,4 @@ -Name:Goat +Name:Goat Token ManaCost:no cost Types:Creature Goat Colors:white diff --git a/forge-gui/res/tokenscripts/w_0_3_wall_defender.txt b/forge-gui/res/tokenscripts/w_0_3_wall_defender.txt index 7e5d45f4219..da45aec9e9d 100644 --- a/forge-gui/res/tokenscripts/w_0_3_wall_defender.txt +++ b/forge-gui/res/tokenscripts/w_0_3_wall_defender.txt @@ -1,4 +1,4 @@ -Name:Wall +Name:Wall Token ManaCost:no cost Types:Creature Wall Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_bird_flying.txt b/forge-gui/res/tokenscripts/w_1_1_bird_flying.txt index 3184c9825ad..4cd00de705d 100644 --- a/forge-gui/res/tokenscripts/w_1_1_bird_flying.txt +++ b/forge-gui/res/tokenscripts/w_1_1_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Bird +Name:Bird Token ManaCost:no cost Types:Creature Bird Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_bird_soldier_flying.txt b/forge-gui/res/tokenscripts/w_1_1_bird_soldier_flying.txt index 623675f4b11..3145cc0fcde 100644 --- a/forge-gui/res/tokenscripts/w_1_1_bird_soldier_flying.txt +++ b/forge-gui/res/tokenscripts/w_1_1_bird_soldier_flying.txt @@ -1,4 +1,4 @@ -Name:Bird Soldier +Name:Bird Soldier Token ManaCost:no cost Types:Creature Bird Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_cat.txt b/forge-gui/res/tokenscripts/w_1_1_cat.txt index e7461356d7b..ddab95a5433 100644 --- a/forge-gui/res/tokenscripts/w_1_1_cat.txt +++ b/forge-gui/res/tokenscripts/w_1_1_cat.txt @@ -1,4 +1,4 @@ -Name:Cat +Name:Cat Token ManaCost:no cost PT:1/1 Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_cat_bird_flying.txt b/forge-gui/res/tokenscripts/w_1_1_cat_bird_flying.txt index 2b9d9e2852a..d304c2ad464 100644 --- a/forge-gui/res/tokenscripts/w_1_1_cat_bird_flying.txt +++ b/forge-gui/res/tokenscripts/w_1_1_cat_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Cat Bird +Name:Cat Bird Token ManaCost:no cost Types:Creature Cat Bird Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_cat_lifelink.txt b/forge-gui/res/tokenscripts/w_1_1_cat_lifelink.txt index 468788b3547..d9095ba9d4a 100644 --- a/forge-gui/res/tokenscripts/w_1_1_cat_lifelink.txt +++ b/forge-gui/res/tokenscripts/w_1_1_cat_lifelink.txt @@ -1,4 +1,4 @@ -Name:Cat +Name:Cat Token ManaCost:no cost Types:Creature Cat Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_cat_soldier_vigilance.txt b/forge-gui/res/tokenscripts/w_1_1_cat_soldier_vigilance.txt index 436a19066b8..a43f079efc5 100644 --- a/forge-gui/res/tokenscripts/w_1_1_cat_soldier_vigilance.txt +++ b/forge-gui/res/tokenscripts/w_1_1_cat_soldier_vigilance.txt @@ -1,4 +1,4 @@ -Name:Cat Soldier +Name:Cat Soldier Token ManaCost:no cost Types:Creature Cat Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_citizen.txt b/forge-gui/res/tokenscripts/w_1_1_citizen.txt index 3e47d6d40b1..c82fe6110ad 100644 --- a/forge-gui/res/tokenscripts/w_1_1_citizen.txt +++ b/forge-gui/res/tokenscripts/w_1_1_citizen.txt @@ -1,4 +1,4 @@ -Name:Citizen +Name:Citizen Token ManaCost:no cost Types:Creature Citizen Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_cleric_lifelink.txt b/forge-gui/res/tokenscripts/w_1_1_cleric_lifelink.txt index fbc824fe060..1734071261c 100644 --- a/forge-gui/res/tokenscripts/w_1_1_cleric_lifelink.txt +++ b/forge-gui/res/tokenscripts/w_1_1_cleric_lifelink.txt @@ -1,4 +1,4 @@ -Name:Cleric +Name:Cleric Token ManaCost:no cost Types:Creature Cleric Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_dog.txt b/forge-gui/res/tokenscripts/w_1_1_dog.txt index 55cedadbe99..e38e28fbb16 100644 --- a/forge-gui/res/tokenscripts/w_1_1_dog.txt +++ b/forge-gui/res/tokenscripts/w_1_1_dog.txt @@ -1,4 +1,4 @@ -Name:Dog +Name:Dog Token ManaCost:no cost PT:1/1 Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_e_soldier.txt b/forge-gui/res/tokenscripts/w_1_1_e_soldier.txt index cffdbc5ad4d..cdb86fd26f2 100644 --- a/forge-gui/res/tokenscripts/w_1_1_e_soldier.txt +++ b/forge-gui/res/tokenscripts/w_1_1_e_soldier.txt @@ -1,4 +1,4 @@ -Name:Soldier +Name:Soldier Token ManaCost:no cost Types:Enchantment Creature Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_human.txt b/forge-gui/res/tokenscripts/w_1_1_human.txt index d7f77a9fcf1..fef603ed80d 100644 --- a/forge-gui/res/tokenscripts/w_1_1_human.txt +++ b/forge-gui/res/tokenscripts/w_1_1_human.txt @@ -1,4 +1,4 @@ -Name:Human +Name:Human Token ManaCost:no cost Types:Creature Human Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_human_soldier.txt b/forge-gui/res/tokenscripts/w_1_1_human_soldier.txt index 6646ebaddae..6e219cd35ad 100644 --- a/forge-gui/res/tokenscripts/w_1_1_human_soldier.txt +++ b/forge-gui/res/tokenscripts/w_1_1_human_soldier.txt @@ -1,4 +1,4 @@ -Name:Human Soldier +Name:Human Soldier Token ManaCost:no cost Types:Creature Human Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_human_warrior.txt b/forge-gui/res/tokenscripts/w_1_1_human_warrior.txt index 0785e9c68f2..68096b9ba0f 100644 --- a/forge-gui/res/tokenscripts/w_1_1_human_warrior.txt +++ b/forge-gui/res/tokenscripts/w_1_1_human_warrior.txt @@ -1,4 +1,4 @@ -Name:Human Warrior +Name:Human Warrior Token ManaCost:no cost Types:Creature Human Warrior Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_kithkin_soldier.txt b/forge-gui/res/tokenscripts/w_1_1_kithkin_soldier.txt index 2b35c792595..6bcfe6f8b04 100644 --- a/forge-gui/res/tokenscripts/w_1_1_kithkin_soldier.txt +++ b/forge-gui/res/tokenscripts/w_1_1_kithkin_soldier.txt @@ -1,4 +1,4 @@ -Name:Kithkin Soldier +Name:Kithkin Soldier Token ManaCost:no cost Types:Creature Kithkin Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_knight_banding.txt b/forge-gui/res/tokenscripts/w_1_1_knight_banding.txt index da9fbafb0ef..418ffed4034 100644 --- a/forge-gui/res/tokenscripts/w_1_1_knight_banding.txt +++ b/forge-gui/res/tokenscripts/w_1_1_knight_banding.txt @@ -1,4 +1,4 @@ -Name:Knight +Name:Knight Token ManaCost:no cost Colors:white Types:Creature Knight diff --git a/forge-gui/res/tokenscripts/w_1_1_kor_ally.txt b/forge-gui/res/tokenscripts/w_1_1_kor_ally.txt index 2db2f568421..ae018d2656f 100644 --- a/forge-gui/res/tokenscripts/w_1_1_kor_ally.txt +++ b/forge-gui/res/tokenscripts/w_1_1_kor_ally.txt @@ -1,4 +1,4 @@ -Name:Kor Ally +Name:Kor Ally Token ManaCost:no cost Types:Creature Kor Ally Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_kor_soldier.txt b/forge-gui/res/tokenscripts/w_1_1_kor_soldier.txt index 5b0f18bf67a..1682be99f49 100644 --- a/forge-gui/res/tokenscripts/w_1_1_kor_soldier.txt +++ b/forge-gui/res/tokenscripts/w_1_1_kor_soldier.txt @@ -1,4 +1,4 @@ -Name:Kor Soldier +Name:Kor Soldier Token ManaCost:no cost Types:Creature Kor Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_kor_warrior.txt b/forge-gui/res/tokenscripts/w_1_1_kor_warrior.txt index d17f06992fe..f6a48a0b50d 100644 --- a/forge-gui/res/tokenscripts/w_1_1_kor_warrior.txt +++ b/forge-gui/res/tokenscripts/w_1_1_kor_warrior.txt @@ -1,4 +1,4 @@ -Name:Kor Warrior +Name:Kor Warrior Token ManaCost:no cost Types:Creature Kor Warrior Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_monk_prowess.txt b/forge-gui/res/tokenscripts/w_1_1_monk_prowess.txt index 24b7a0af127..8e3badcc277 100644 --- a/forge-gui/res/tokenscripts/w_1_1_monk_prowess.txt +++ b/forge-gui/res/tokenscripts/w_1_1_monk_prowess.txt @@ -1,4 +1,4 @@ -Name:Monk +Name:Monk Token ManaCost:no cost Types:Creature Monk Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_mouse.txt b/forge-gui/res/tokenscripts/w_1_1_mouse.txt index 271087cc533..a9cc9885e14 100644 --- a/forge-gui/res/tokenscripts/w_1_1_mouse.txt +++ b/forge-gui/res/tokenscripts/w_1_1_mouse.txt @@ -1,4 +1,4 @@ -Name:Mouse +Name:Mouse Token ManaCost:no cost Types:Creature Mouse Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_pegasus_flying.txt b/forge-gui/res/tokenscripts/w_1_1_pegasus_flying.txt index 41d12a82915..6791d01a6c2 100644 --- a/forge-gui/res/tokenscripts/w_1_1_pegasus_flying.txt +++ b/forge-gui/res/tokenscripts/w_1_1_pegasus_flying.txt @@ -1,4 +1,4 @@ -Name:Pegasus +Name:Pegasus Token ManaCost:no cost Types:Creature Pegasus Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_soldier.txt b/forge-gui/res/tokenscripts/w_1_1_soldier.txt index 1226bf902ab..eab82574f8d 100644 --- a/forge-gui/res/tokenscripts/w_1_1_soldier.txt +++ b/forge-gui/res/tokenscripts/w_1_1_soldier.txt @@ -1,4 +1,4 @@ -Name:Soldier +Name:Soldier Token ManaCost:no cost Types:Creature Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_soldier_ally.txt b/forge-gui/res/tokenscripts/w_1_1_soldier_ally.txt index 57388e8b7c2..07d7b8df618 100644 --- a/forge-gui/res/tokenscripts/w_1_1_soldier_ally.txt +++ b/forge-gui/res/tokenscripts/w_1_1_soldier_ally.txt @@ -1,4 +1,4 @@ -Name:Soldier Ally +Name:Soldier Ally Token ManaCost:no cost Types:Creature Soldier Ally Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_soldier_lifelink.txt b/forge-gui/res/tokenscripts/w_1_1_soldier_lifelink.txt index d5b983de7ae..cfb95da290f 100644 --- a/forge-gui/res/tokenscripts/w_1_1_soldier_lifelink.txt +++ b/forge-gui/res/tokenscripts/w_1_1_soldier_lifelink.txt @@ -1,4 +1,4 @@ -Name:Soldier +Name:Soldier Token ManaCost:no cost Types:Creature Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_spirit_flying.txt b/forge-gui/res/tokenscripts/w_1_1_spirit_flying.txt index 39cf47f4bac..425d6ecc3df 100644 --- a/forge-gui/res/tokenscripts/w_1_1_spirit_flying.txt +++ b/forge-gui/res/tokenscripts/w_1_1_spirit_flying.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Creature Spirit Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_vampire_lifelink.txt b/forge-gui/res/tokenscripts/w_1_1_vampire_lifelink.txt index af62144d2c1..01f33cc970c 100644 --- a/forge-gui/res/tokenscripts/w_1_1_vampire_lifelink.txt +++ b/forge-gui/res/tokenscripts/w_1_1_vampire_lifelink.txt @@ -1,4 +1,4 @@ -Name:Vampire +Name:Vampire Token ManaCost:no cost Types:Creature Vampire Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_warrior.txt b/forge-gui/res/tokenscripts/w_1_1_warrior.txt index b8469fa1922..759b3545851 100644 --- a/forge-gui/res/tokenscripts/w_1_1_warrior.txt +++ b/forge-gui/res/tokenscripts/w_1_1_warrior.txt @@ -1,4 +1,4 @@ -Name:Warrior +Name:Warrior Token ManaCost:no cost Types:Creature Warrior Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_1_warrior_vigilance.txt b/forge-gui/res/tokenscripts/w_1_1_warrior_vigilance.txt index 0eb3e9c1475..a81db94d018 100644 --- a/forge-gui/res/tokenscripts/w_1_1_warrior_vigilance.txt +++ b/forge-gui/res/tokenscripts/w_1_1_warrior_vigilance.txt @@ -1,4 +1,4 @@ -Name:Warrior +Name:Warrior Token ManaCost:no cost Types:Creature Warrior Colors:white diff --git a/forge-gui/res/tokenscripts/w_1_2_soldier_defender.txt b/forge-gui/res/tokenscripts/w_1_2_soldier_defender.txt index b45119470c9..7764448014e 100644 --- a/forge-gui/res/tokenscripts/w_1_2_soldier_defender.txt +++ b/forge-gui/res/tokenscripts/w_1_2_soldier_defender.txt @@ -1,4 +1,4 @@ -Name:Soldier +Name:Soldier Token ManaCost:no cost Types:Creature Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_1_e_cleric.txt b/forge-gui/res/tokenscripts/w_2_1_e_cleric.txt index 409b1415f8e..338fbb71d57 100644 --- a/forge-gui/res/tokenscripts/w_2_1_e_cleric.txt +++ b/forge-gui/res/tokenscripts/w_2_1_e_cleric.txt @@ -1,4 +1,4 @@ -Name:Cleric +Name:Cleric Token ManaCost:no cost Types:Enchantment Creature Cleric Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_cat.txt b/forge-gui/res/tokenscripts/w_2_2_cat.txt index f7258323cdb..add9f30989f 100644 --- a/forge-gui/res/tokenscripts/w_2_2_cat.txt +++ b/forge-gui/res/tokenscripts/w_2_2_cat.txt @@ -1,4 +1,4 @@ -Name:Cat +Name:Cat Token ManaCost:no cost Types:Creature Cat Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_cat_beast.txt b/forge-gui/res/tokenscripts/w_2_2_cat_beast.txt index 7420a6b003e..9fdfeb446e5 100644 --- a/forge-gui/res/tokenscripts/w_2_2_cat_beast.txt +++ b/forge-gui/res/tokenscripts/w_2_2_cat_beast.txt @@ -1,4 +1,4 @@ -Name:Cat Beast +Name:Cat Beast Token ManaCost:no cost Types:Creature Cat Beast Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_griffin_flying.txt b/forge-gui/res/tokenscripts/w_2_2_griffin_flying.txt index 7f8e6c5fadb..73fa8215407 100644 --- a/forge-gui/res/tokenscripts/w_2_2_griffin_flying.txt +++ b/forge-gui/res/tokenscripts/w_2_2_griffin_flying.txt @@ -1,4 +1,4 @@ -Name:Griffin +Name:Griffin Token ManaCost:no cost Types:Creature Griffin Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_knight.txt b/forge-gui/res/tokenscripts/w_2_2_knight.txt index 44a1080da69..194237dac79 100644 --- a/forge-gui/res/tokenscripts/w_2_2_knight.txt +++ b/forge-gui/res/tokenscripts/w_2_2_knight.txt @@ -1,4 +1,4 @@ -Name:Knight +Name:Knight Token ManaCost:no cost Types:Creature Knight Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_knight_ally.txt b/forge-gui/res/tokenscripts/w_2_2_knight_ally.txt index 9d6da5a12f2..a4fccbf97d4 100644 --- a/forge-gui/res/tokenscripts/w_2_2_knight_ally.txt +++ b/forge-gui/res/tokenscripts/w_2_2_knight_ally.txt @@ -1,4 +1,4 @@ -Name:Knight Ally +Name:Knight Ally Token ManaCost:no cost Types:Creature Knight Ally Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_knight_first_strike.txt b/forge-gui/res/tokenscripts/w_2_2_knight_first_strike.txt index c8481982843..2db6eca9c53 100644 --- a/forge-gui/res/tokenscripts/w_2_2_knight_first_strike.txt +++ b/forge-gui/res/tokenscripts/w_2_2_knight_first_strike.txt @@ -1,4 +1,4 @@ -Name:Knight +Name:Knight Token ManaCost:no cost Types:Creature Knight Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_knight_vigilance.txt b/forge-gui/res/tokenscripts/w_2_2_knight_vigilance.txt index f48acd0d058..eb6100dbdbb 100644 --- a/forge-gui/res/tokenscripts/w_2_2_knight_vigilance.txt +++ b/forge-gui/res/tokenscripts/w_2_2_knight_vigilance.txt @@ -1,4 +1,4 @@ -Name:Knight +Name:Knight Token ManaCost:no cost Types:Creature Knight Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_pegasus_flying.txt b/forge-gui/res/tokenscripts/w_2_2_pegasus_flying.txt index 977cb1c082d..aead31912e5 100644 --- a/forge-gui/res/tokenscripts/w_2_2_pegasus_flying.txt +++ b/forge-gui/res/tokenscripts/w_2_2_pegasus_flying.txt @@ -1,4 +1,4 @@ -Name:Pegasus +Name:Pegasus Token ManaCost:no cost Types:Creature Pegasus Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_reflection.txt b/forge-gui/res/tokenscripts/w_2_2_reflection.txt index bf50cbf6774..73c4229583e 100644 --- a/forge-gui/res/tokenscripts/w_2_2_reflection.txt +++ b/forge-gui/res/tokenscripts/w_2_2_reflection.txt @@ -1,4 +1,4 @@ -Name:Reflection +Name:Reflection Token ManaCost:no cost PT:2/2 Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_soldier_vigilance.txt b/forge-gui/res/tokenscripts/w_2_2_soldier_vigilance.txt index fc1ac16ecd1..e231a61690f 100644 --- a/forge-gui/res/tokenscripts/w_2_2_soldier_vigilance.txt +++ b/forge-gui/res/tokenscripts/w_2_2_soldier_vigilance.txt @@ -1,4 +1,4 @@ -Name:Soldier +Name:Soldier Token ManaCost:no cost Types:Creature Soldier Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_2_unicorn.txt b/forge-gui/res/tokenscripts/w_2_2_unicorn.txt index 60e011798a2..8475602666f 100644 --- a/forge-gui/res/tokenscripts/w_2_2_unicorn.txt +++ b/forge-gui/res/tokenscripts/w_2_2_unicorn.txt @@ -1,4 +1,4 @@ -Name:Unicorn +Name:Unicorn Token ManaCost:no cost Types:Creature Unicorn Colors:white diff --git a/forge-gui/res/tokenscripts/w_2_4_ox.txt b/forge-gui/res/tokenscripts/w_2_4_ox.txt index 2d5461d9ff3..9eabe496941 100644 --- a/forge-gui/res/tokenscripts/w_2_4_ox.txt +++ b/forge-gui/res/tokenscripts/w_2_4_ox.txt @@ -1,4 +1,4 @@ -Name:Ox +Name:Ox Token ManaCost:no cost PT:2/4 Colors:white diff --git a/forge-gui/res/tokenscripts/w_3_3_angel_flying.txt b/forge-gui/res/tokenscripts/w_3_3_angel_flying.txt index 67f9eb70c08..7532d183427 100644 --- a/forge-gui/res/tokenscripts/w_3_3_angel_flying.txt +++ b/forge-gui/res/tokenscripts/w_3_3_angel_flying.txt @@ -1,4 +1,4 @@ -Name:Angel +Name:Angel Token ManaCost:no cost Types:Creature Angel Colors:white diff --git a/forge-gui/res/tokenscripts/w_3_3_bird_flying.txt b/forge-gui/res/tokenscripts/w_3_3_bird_flying.txt index 372591cd214..41656079a90 100644 --- a/forge-gui/res/tokenscripts/w_3_3_bird_flying.txt +++ b/forge-gui/res/tokenscripts/w_3_3_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Bird +Name:Bird Token ManaCost:no cost Types:Creature Bird Colors:white diff --git a/forge-gui/res/tokenscripts/w_3_3_spirit_flying.txt b/forge-gui/res/tokenscripts/w_3_3_spirit_flying.txt index 37962fd2159..47ee5703546 100644 --- a/forge-gui/res/tokenscripts/w_3_3_spirit_flying.txt +++ b/forge-gui/res/tokenscripts/w_3_3_spirit_flying.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Creature Spirit Colors:white diff --git a/forge-gui/res/tokenscripts/w_3_4_bird_flying.txt b/forge-gui/res/tokenscripts/w_3_4_bird_flying.txt index 19369e3ff57..0bfc49d98e6 100644 --- a/forge-gui/res/tokenscripts/w_3_4_bird_flying.txt +++ b/forge-gui/res/tokenscripts/w_3_4_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Bird +Name:Bird Token ManaCost:no cost Types:Creature Bird Colors:white diff --git a/forge-gui/res/tokenscripts/w_4_4_angel_flying.txt b/forge-gui/res/tokenscripts/w_4_4_angel_flying.txt index 61a43654b3e..db6830bb0cc 100644 --- a/forge-gui/res/tokenscripts/w_4_4_angel_flying.txt +++ b/forge-gui/res/tokenscripts/w_4_4_angel_flying.txt @@ -1,4 +1,4 @@ -Name:Angel +Name:Angel Token ManaCost:no cost Types:Creature Angel Colors:white diff --git a/forge-gui/res/tokenscripts/w_4_4_angel_flying_vigilance.txt b/forge-gui/res/tokenscripts/w_4_4_angel_flying_vigilance.txt index 1acb72442c5..ed2c7bb4c2e 100644 --- a/forge-gui/res/tokenscripts/w_4_4_angel_flying_vigilance.txt +++ b/forge-gui/res/tokenscripts/w_4_4_angel_flying_vigilance.txt @@ -1,4 +1,4 @@ -Name:Angel +Name:Angel Token ManaCost:no cost Types:Creature Angel Colors:white diff --git a/forge-gui/res/tokenscripts/w_4_4_angel_warrior_flying.txt b/forge-gui/res/tokenscripts/w_4_4_angel_warrior_flying.txt index c6da271178a..a1464e40138 100644 --- a/forge-gui/res/tokenscripts/w_4_4_angel_warrior_flying.txt +++ b/forge-gui/res/tokenscripts/w_4_4_angel_warrior_flying.txt @@ -1,4 +1,4 @@ -Name:Angel Warrior +Name:Angel Warrior Token ManaCost:no cost Types:Creature Angel Warrior Colors:white diff --git a/forge-gui/res/tokenscripts/w_4_4_angel_warrior_flying_vigilance.txt b/forge-gui/res/tokenscripts/w_4_4_angel_warrior_flying_vigilance.txt index 875421fce49..6dd596a042e 100644 --- a/forge-gui/res/tokenscripts/w_4_4_angel_warrior_flying_vigilance.txt +++ b/forge-gui/res/tokenscripts/w_4_4_angel_warrior_flying_vigilance.txt @@ -1,4 +1,4 @@ -Name:Angel Warrior +Name:Angel Warrior Token ManaCost:no cost Types:Creature Angel Warrior Colors:white diff --git a/forge-gui/res/tokenscripts/w_4_4_avatar_flying.txt b/forge-gui/res/tokenscripts/w_4_4_avatar_flying.txt index 425fc476d06..831ba8b31b4 100644 --- a/forge-gui/res/tokenscripts/w_4_4_avatar_flying.txt +++ b/forge-gui/res/tokenscripts/w_4_4_avatar_flying.txt @@ -1,4 +1,4 @@ -Name:Avatar +Name:Avatar Token ManaCost:no cost Types:Creature Avatar Colors:white diff --git a/forge-gui/res/tokenscripts/w_4_4_elemental_flying.txt b/forge-gui/res/tokenscripts/w_4_4_elemental_flying.txt index 9fc9c2f117f..89564587e54 100644 --- a/forge-gui/res/tokenscripts/w_4_4_elemental_flying.txt +++ b/forge-gui/res/tokenscripts/w_4_4_elemental_flying.txt @@ -1,4 +1,4 @@ -Name:Elemental +Name:Elemental Token ManaCost:no cost Types:Creature Elemental Colors:white diff --git a/forge-gui/res/tokenscripts/w_4_4_spirit_flying.txt b/forge-gui/res/tokenscripts/w_4_4_spirit_flying.txt index f93b7ac1154..e14d42ee70c 100644 --- a/forge-gui/res/tokenscripts/w_4_4_spirit_flying.txt +++ b/forge-gui/res/tokenscripts/w_4_4_spirit_flying.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Creature Spirit Colors:white diff --git a/forge-gui/res/tokenscripts/w_5_5_giant_warrior.txt b/forge-gui/res/tokenscripts/w_5_5_giant_warrior.txt index d0a2732963f..f57c87bc9ad 100644 --- a/forge-gui/res/tokenscripts/w_5_5_giant_warrior.txt +++ b/forge-gui/res/tokenscripts/w_5_5_giant_warrior.txt @@ -1,4 +1,4 @@ -Name:Giant Warrior +Name:Giant Warrior Token ManaCost:no cost PT:5/5 Colors:white diff --git a/forge-gui/res/tokenscripts/w_5_5_horse.txt b/forge-gui/res/tokenscripts/w_5_5_horse.txt index 1681138cf2b..f3aa6160ca0 100644 --- a/forge-gui/res/tokenscripts/w_5_5_horse.txt +++ b/forge-gui/res/tokenscripts/w_5_5_horse.txt @@ -1,4 +1,4 @@ -Name:Horse +Name:Horse Token ManaCost:no cost PT:5/5 Colors:white diff --git a/forge-gui/res/tokenscripts/w_x_x_avatar_life_total.txt b/forge-gui/res/tokenscripts/w_x_x_avatar_life_total.txt index 82b2f799b28..c6eb1d9ba0a 100644 --- a/forge-gui/res/tokenscripts/w_x_x_avatar_life_total.txt +++ b/forge-gui/res/tokenscripts/w_x_x_avatar_life_total.txt @@ -1,4 +1,4 @@ -Name:Avatar +Name:Avatar Token ManaCost:no cost Types:Creature Avatar Colors:white diff --git a/forge-gui/res/tokenscripts/w_x_x_reflection.txt b/forge-gui/res/tokenscripts/w_x_x_reflection.txt index fcf22121331..a169129d6a6 100644 --- a/forge-gui/res/tokenscripts/w_x_x_reflection.txt +++ b/forge-gui/res/tokenscripts/w_x_x_reflection.txt @@ -1,4 +1,4 @@ -Name:Reflection +Name:Reflection Token ManaCost:no cost PT:*/* Colors:white diff --git a/forge-gui/res/tokenscripts/w_x_x_spirit_cleric_total_spirits.txt b/forge-gui/res/tokenscripts/w_x_x_spirit_cleric_total_spirits.txt index bb448405bd0..5d5f05d79ad 100644 --- a/forge-gui/res/tokenscripts/w_x_x_spirit_cleric_total_spirits.txt +++ b/forge-gui/res/tokenscripts/w_x_x_spirit_cleric_total_spirits.txt @@ -1,4 +1,4 @@ -Name:Spirit Cleric +Name:Spirit Cleric Token ManaCost:no cost Types:Creature Spirit Cleric PT:*/* diff --git a/forge-gui/res/tokenscripts/wb_1_1_cleric_deathpact.txt b/forge-gui/res/tokenscripts/wb_1_1_cleric_deathpact.txt index 18f791cda50..f5908e06035 100644 --- a/forge-gui/res/tokenscripts/wb_1_1_cleric_deathpact.txt +++ b/forge-gui/res/tokenscripts/wb_1_1_cleric_deathpact.txt @@ -1,4 +1,4 @@ -Name:Cleric +Name:Cleric Token ManaCost:no cost Types:Creature Cleric Colors:white,black diff --git a/forge-gui/res/tokenscripts/wb_1_1_human_cleric.txt b/forge-gui/res/tokenscripts/wb_1_1_human_cleric.txt index a5df08c8cd7..58856cccad2 100644 --- a/forge-gui/res/tokenscripts/wb_1_1_human_cleric.txt +++ b/forge-gui/res/tokenscripts/wb_1_1_human_cleric.txt @@ -1,4 +1,4 @@ -Name:Human Cleric +Name:Human Cleric Token ManaCost:no cost Types:Creature Human Cleric Colors:white,black diff --git a/forge-gui/res/tokenscripts/wb_1_1_spirit_flying.txt b/forge-gui/res/tokenscripts/wb_1_1_spirit_flying.txt index 9fe27496ea8..f1a97597036 100644 --- a/forge-gui/res/tokenscripts/wb_1_1_spirit_flying.txt +++ b/forge-gui/res/tokenscripts/wb_1_1_spirit_flying.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Creature Spirit Colors:white,black diff --git a/forge-gui/res/tokenscripts/wb_1_1_vampire_lifelink.txt b/forge-gui/res/tokenscripts/wb_1_1_vampire_lifelink.txt index c087c941b6a..a71e2e1e653 100644 --- a/forge-gui/res/tokenscripts/wb_1_1_vampire_lifelink.txt +++ b/forge-gui/res/tokenscripts/wb_1_1_vampire_lifelink.txt @@ -1,4 +1,4 @@ -Name:Vampire +Name:Vampire Token ManaCost:no cost Types:Creature Vampire Colors:white,black diff --git a/forge-gui/res/tokenscripts/wb_2_1_inkling_flying.txt b/forge-gui/res/tokenscripts/wb_2_1_inkling_flying.txt index 5e47464a41d..a60f3428ed2 100644 --- a/forge-gui/res/tokenscripts/wb_2_1_inkling_flying.txt +++ b/forge-gui/res/tokenscripts/wb_2_1_inkling_flying.txt @@ -1,4 +1,4 @@ -Name:Inkling +Name:Inkling Token ManaCost:no cost Types:Creature Inkling Colors:white,black diff --git a/forge-gui/res/tokenscripts/wb_x_x_e_spirit_experience.txt b/forge-gui/res/tokenscripts/wb_x_x_e_spirit_experience.txt index a605c668a32..650c8baaaa0 100644 --- a/forge-gui/res/tokenscripts/wb_x_x_e_spirit_experience.txt +++ b/forge-gui/res/tokenscripts/wb_x_x_e_spirit_experience.txt @@ -1,4 +1,4 @@ -Name:Spirit +Name:Spirit Token ManaCost:no cost Types:Enchantment Creature Spirit Colors:white,black diff --git a/forge-gui/res/tokenscripts/wu_1_1_bird_flying.txt b/forge-gui/res/tokenscripts/wu_1_1_bird_flying.txt index a9b1cd4d272..1b10ee350cc 100644 --- a/forge-gui/res/tokenscripts/wu_1_1_bird_flying.txt +++ b/forge-gui/res/tokenscripts/wu_1_1_bird_flying.txt @@ -1,4 +1,4 @@ -Name:Bird +Name:Bird Token ManaCost:no cost Types:Creature Bird Colors:white,blue diff --git a/forge-gui/res/tokenscripts/wu_4_4_sphinx_flying_vigilance.txt b/forge-gui/res/tokenscripts/wu_4_4_sphinx_flying_vigilance.txt index fbf23263825..6fe9ac3edf7 100644 --- a/forge-gui/res/tokenscripts/wu_4_4_sphinx_flying_vigilance.txt +++ b/forge-gui/res/tokenscripts/wu_4_4_sphinx_flying_vigilance.txt @@ -1,4 +1,4 @@ -Name:Sphinx +Name:Sphinx Token ManaCost:no cost Types:Creature Sphinx Colors:white,blue diff --git a/forge-gui/res/tokenscripts/wubrg_2_2_citizen.txt b/forge-gui/res/tokenscripts/wubrg_2_2_citizen.txt index 83130f1e978..e1e5947cc0b 100644 --- a/forge-gui/res/tokenscripts/wubrg_2_2_citizen.txt +++ b/forge-gui/res/tokenscripts/wubrg_2_2_citizen.txt @@ -1,4 +1,4 @@ -Name:Citizen +Name:Citizen Token Types: Creature Citizen Colors:white,blue,black,red,green ManaCost: no cost diff --git a/forge-gui/src/main/java/forge/gamemodes/limited/CardThemedDeckBuilder.java b/forge-gui/src/main/java/forge/gamemodes/limited/CardThemedDeckBuilder.java index aa7d7ebd81d..903868338a1 100644 --- a/forge-gui/src/main/java/forge/gamemodes/limited/CardThemedDeckBuilder.java +++ b/forge-gui/src/main/java/forge/gamemodes/limited/CardThemedDeckBuilder.java @@ -216,8 +216,7 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { System.out.println("Post more creatures and spells : " + deckList.size()); } - // 5. If there are still on-color cards, and the average cmc is low, add - // extras. + // 5. If there are still on-color cards, and the average cmc is low, add extras. double avCMC = getAverageCMC(deckList); //calculated required lands based on https://www.channelfireball.com/articles/how-many-lands-do-you-need-to-consistently-hit-your-land-drops/ float baseLandParameter = 16f; @@ -326,14 +325,12 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { aiPlayables.remove(sbCard); rankedColorList.remove(sbCard); - ++i; } if (logToConsole) { debugFinalDeck(); } return result; - } //Extend to playsets for non land cards to fill out deck for when no other suitable cards are available @@ -714,7 +711,6 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { while (deckList.size() > targetSize) { deckList.remove(deckList.size() - 1); } - } /** @@ -872,9 +868,7 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { Collections.shuffle(possibleList); //addManaCurveCards(CardRanker.rankCardsInDeck(possibleList.subList(0, targetSize*3 <= possibleList.size() ? targetSize*3 : possibleList.size())), //num, "Random Card"); - addManaCurveCards(possibleList, - num, "Random Card"); - + addManaCurveCards(possibleList, num, "Random Card"); } /** diff --git a/forge-gui/src/main/java/forge/gamemodes/match/HostedMatch.java b/forge-gui/src/main/java/forge/gamemodes/match/HostedMatch.java index d86b05d0d26..8cca6f6bd9c 100644 --- a/forge-gui/src/main/java/forge/gamemodes/match/HostedMatch.java +++ b/forge-gui/src/main/java/forge/gamemodes/match/HostedMatch.java @@ -89,6 +89,7 @@ public class HostedMatch { gameRules.setSideboardForAI(FModel.getPreferences().getPrefBoolean(FPref.MATCH_SIDEBOARD_FOR_AI)); gameRules.setCanCloneUseTargetsImage(FModel.getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE)); gameRules.setUseGrayText(FModel.getPreferences().getPrefBoolean(FPref.UI_GRAY_INACTIVE_TEXT)); + gameRules.setGamesPerMatch(FModel.getPreferences().getPrefInt(FPref.UI_MATCHES_PER_GAME)); return gameRules; } diff --git a/forge-gui/src/main/java/forge/gamemodes/match/input/InputPassPriority.java b/forge-gui/src/main/java/forge/gamemodes/match/input/InputPassPriority.java index e03303b52c7..868b6f5aab9 100644 --- a/forge-gui/src/main/java/forge/gamemodes/match/input/InputPassPriority.java +++ b/forge-gui/src/main/java/forge/gamemodes/match/input/InputPassPriority.java @@ -110,7 +110,7 @@ public class InputPassPriority extends InputSyncronizedBase { public void run() { Localizer localizer = Localizer.getInstance(); String message = localizer.getMessage("lblYouHaveManaFloatingInYourManaPoolCouldBeLostIfPassPriority"); - if (FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN)) { + if (player.getManaPool().hasBurn()) { message += " " + localizer.getMessage("lblYouWillTakeManaBurnDamageEqualAmountFloatingManaLostThisWay"); } if (getController().getGui().showConfirmDialog(message, localizer.getMessage("lblManaFloating"), localizer.getMessage("lblOk"), localizer.getMessage("lblCancel"))) { diff --git a/forge-gui/src/main/java/forge/gamemodes/quest/QuestEventDraft.java b/forge-gui/src/main/java/forge/gamemodes/quest/QuestEventDraft.java index 576670a806b..3ab876622dd 100644 --- a/forge-gui/src/main/java/forge/gamemodes/quest/QuestEventDraft.java +++ b/forge-gui/src/main/java/forge/gamemodes/quest/QuestEventDraft.java @@ -446,13 +446,15 @@ public class QuestEventDraft implements IQuestEvent { private void awardSelectedRare(final QuestDraftPrizes prizes) { final List possibleCards = new ArrayList<>(); + final List cardNames = new ArrayList<>(); for (final CardEdition edition : getAllEditions()) { - for (final CardInSet card : edition.getCards()) { + for (final CardInSet card : edition.getAllCardsInSet()) { if (card.rarity == CardRarity.Rare || card.rarity == CardRarity.MythicRare) { final PaperCard cardToAdd = FModel.getMagicDb().getCommonCards().getCard(card.name, edition.getCode()); - if (cardToAdd != null) { + if (cardToAdd != null && !cardNames.contains(cardToAdd.getName())) { possibleCards.add(cardToAdd); + cardNames.add(cardToAdd.getName()); } } } @@ -470,14 +472,17 @@ public class QuestEventDraft implements IQuestEvent { final CardEdition randomEdition = getRandomEdition(); final List cardsInEdition = new ArrayList<>(); + final List cardNames = new ArrayList<>(); - for (final CardInSet card : randomEdition.getCards()) { + for (final CardInSet card : randomEdition.getAllCardsInSet()) { if (card.rarity == CardRarity.Rare || card.rarity == CardRarity.MythicRare) { - cardsInEdition.add(card); + if (!cardNames.contains(card.name)) { + cardsInEdition.add(card); + cardNames.add(card.name); + } } } - CardInSet randomCard; PaperCard promo = null; diff --git a/forge-gui/src/main/java/forge/gamemodes/tournament/system/AbstractTournament.java b/forge-gui/src/main/java/forge/gamemodes/tournament/system/AbstractTournament.java index 4747832c4b4..ff9871df2d0 100644 --- a/forge-gui/src/main/java/forge/gamemodes/tournament/system/AbstractTournament.java +++ b/forge-gui/src/main/java/forge/gamemodes/tournament/system/AbstractTournament.java @@ -28,8 +28,8 @@ public abstract class AbstractTournament implements Serializable { protected final List completedPairings = new ArrayList<>(); protected final List activePairings = new ArrayList<>(); - public List getCompletedPairings() { return completedPairings; } - public List getActivePairings() { return activePairings; } + public List getCompletedPairings() { return completedPairings; } + public List getActivePairings() { return activePairings; } public AbstractTournament(int ttlRnds) { activeRound = 0; @@ -60,13 +60,13 @@ public abstract class AbstractTournament implements Serializable { public int getActiveRound() { return activeRound; } public int getTotalRounds() { return totalRounds; } - public boolean isContinualPairing() { return continualPairing; } + public boolean isContinualPairing() { return continualPairing; } - public void setContinualPairing(boolean continualPairing) { this.continualPairing = continualPairing; } + public void setContinualPairing(boolean continualPairing) { this.continualPairing = continualPairing; } public boolean isInitialized() { return initialized; } - public void setInitialized(boolean initialized) { this.initialized = initialized; } + public void setInitialized(boolean initialized) { this.initialized = initialized; } public boolean isPlayerRemaining(TournamentPlayer player) { return remainingPlayers.contains(player); @@ -144,7 +144,7 @@ public abstract class AbstractTournament implements Serializable { } } - public List getAllPlayers(){ + public List getAllPlayers() { return allPlayers; } diff --git a/forge-gui/src/main/java/forge/gui/GuiBase.java b/forge-gui/src/main/java/forge/gui/GuiBase.java index b10afbacfce..87717870332 100644 --- a/forge-gui/src/main/java/forge/gui/GuiBase.java +++ b/forge-gui/src/main/java/forge/gui/GuiBase.java @@ -7,6 +7,7 @@ public class GuiBase { private static boolean propertyConfig = true; private static boolean networkplay = false; private static boolean isAndroidport = false; + private static boolean isAdventureMode = false; private static boolean interrupted = false; private static String deviceName = ""; private static String androidRelease = ""; @@ -20,6 +21,9 @@ public class GuiBase { public static void setIsAndroid(boolean value) { isAndroidport = value; } public static boolean isAndroid() { return isAndroidport; } + public static void setIsAdventureMode(boolean value) { isAdventureMode = value; } + public static boolean isAdventureMode() { return isAdventureMode; } + public static void setUsingAppDirectory(boolean value) { usingAppDirectory = value; } public static boolean isUsingAppDirectory() { return usingAppDirectory; } diff --git a/forge-gui/src/main/java/forge/gui/download/GuiDownloadService.java b/forge-gui/src/main/java/forge/gui/download/GuiDownloadService.java index e5b6bc050dd..6465620376c 100644 --- a/forge-gui/src/main/java/forge/gui/download/GuiDownloadService.java +++ b/forge-gui/src/main/java/forge/gui/download/GuiDownloadService.java @@ -145,7 +145,11 @@ public abstract class GuiDownloadService implements Runnable { } private void readyToStart() { - if (files.isEmpty()) { + if (files == null) { + progressBar.setDescription("Connection error?"); + btnStart.setText("OK"); + btnStart.setCommand(cmdClose); + } else if (files.isEmpty()) { progressBar.setDescription("All items have been downloaded."); btnStart.setText("OK"); btnStart.setCommand(cmdClose); diff --git a/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java b/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java index beb4cb86770..20f846048e5 100644 --- a/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java +++ b/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java @@ -68,6 +68,7 @@ public class ForgePreferences extends PreferencesStore { BRAWL_P7_DECK_STATE(""), BRAWL_P8_DECK_STATE(""), UI_LANDSCAPE_MODE ("false"), + UI_MATCHES_PER_GAME("3"), UI_COMPACT_MAIN_MENU ("false"), UI_USE_OLD ("false"), UI_RANDOM_FOIL ("false"), diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 6546810ffb0..31548a29587 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -41,7 +41,6 @@ import forge.ai.GameState; import forge.ai.PlayerControllerAi; import forge.card.CardDb; import forge.card.CardStateName; -import forge.card.CardType; import forge.card.ColorSet; import forge.card.ICardFace; import forge.card.MagicColor; @@ -270,7 +269,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public SpellAbility getAbilityToPlay(final Card hostCard, final List abilities, final ITriggerEvent triggerEvent) { // make sure another human player can't choose opponents cards just because he might see them - if (triggerEvent != null && !hostCard.isInZone(ZoneType.Battlefield) && !hostCard.getOwner().equals(player) && + if (triggerEvent != null && !hostCard.isInPlay() && !hostCard.getOwner().equals(player) && !hostCard.getController().equals(player) && // If player cast Shaman's Trance, they can play spells from any Graveyard (if other effects allow it to be cast) (!player.hasKeyword("Shaman's Trance") || !hostCard.isInZone(ZoneType.Graveyard))) { @@ -1272,7 +1271,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont continue; } // same is true if it somehow has all creature types - if (c.getType().hasSubtype(CardType.AllCreatureTypes)) { + if (c.getType().hasAllCreatureTypes()) { continue; } // ignore cards that does enter the battlefield as clones