diff --git a/.mvn/local-settings.xml b/.mvn/local-settings.xml new file mode 100644 index 00000000000..3abc1df0e86 --- /dev/null +++ b/.mvn/local-settings.xml @@ -0,0 +1,15 @@ + + + + + 4thline-repo-http-unblocker + 4thline-repo + + http://4thline.org/m2 + + + \ No newline at end of file diff --git a/.mvn/maven.config b/.mvn/maven.config new file mode 100644 index 00000000000..2965a02fc81 --- /dev/null +++ b/.mvn/maven.config @@ -0,0 +1 @@ +--settings ./.mvn/local-settings.xml \ No newline at end of file diff --git a/forge-ai/src/main/java/forge/ai/AiAttackController.java b/forge-ai/src/main/java/forge/ai/AiAttackController.java index 94ef70f394d..fa600d9bbce 100644 --- a/forge-ai/src/main/java/forge/ai/AiAttackController.java +++ b/forge-ai/src/main/java/forge/ai/AiAttackController.java @@ -624,7 +624,7 @@ public class AiAttackController { // Attempt to see if there's a defined entity that must be attacked strictly this turn... GameEntity entity = ai.getMustAttackEntityThisTurn(); - if (entity == null) { + if (nextTurn || entity == null) { // ...or during the attacking creature controller's turn entity = ai.getMustAttackEntity(); } @@ -720,6 +720,7 @@ public class AiAttackController { continue; } boolean mustAttack = false; + // TODO for nextTurn check if it was temporary if (attacker.isGoaded()) { mustAttack = true; } else if (attacker.getSVar("MustAttack").equals("True")) { @@ -736,7 +737,7 @@ public class AiAttackController { mustAttack = true; } } - if (mustAttack || attacker.getController().getMustAttackEntity() != null || attacker.getController().getMustAttackEntityThisTurn() != null) { + if (mustAttack || (attacker.getController().getMustAttackEntity() != null && nextTurn) || (attacker.getController().getMustAttackEntityThisTurn() != null && !nextTurn)) { combat.addAttacker(attacker, defender); attackersLeft.remove(attacker); numForcedAttackers++; diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index 2ba324f8ddc..bc36997fe18 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -3040,11 +3040,11 @@ public class ComputerUtil { public static boolean aiLifeInDanger(Player ai, boolean serious, int payment) { // TODO should also consider them as teams for (Player opponent: ai.getOpponents()) { - // test whether the human can kill the ai next turn Combat combat = new Combat(opponent); boolean containsAttacker = false; + boolean thisCombat = ai.getGame().getPhaseHandler().isPlayerTurn(opponent) && ai.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_BEGIN); for (Card att : opponent.getCreaturesInPlay()) { - if (ComputerUtilCombat.canAttackNextTurn(att, ai)) { + if ((thisCombat && CombatUtil.canAttack(att, ai)) || (!thisCombat && ComputerUtilCombat.canAttackNextTurn(att, ai))) { combat.addAttacker(att, ai); containsAttacker = true; } @@ -3052,6 +3052,8 @@ public class ComputerUtil { if (!containsAttacker) { continue; } + + // TODO if it's next turn ignore mustBlockCards AiBlockController block = new AiBlockController(ai, false); block.assignBlockersForCombat(combat); diff --git a/forge-ai/src/main/java/forge/ai/ability/DamagePreventAi.java b/forge-ai/src/main/java/forge/ai/ability/DamagePreventAi.java index 8ea6208ffed..806c08fddfd 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamagePreventAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamagePreventAi.java @@ -43,7 +43,7 @@ public class DamagePreventAi extends SpellAbilityAi { final TargetRestrictions tgt = sa.getTargetRestrictions(); if (tgt == null) { // As far as I can tell these Defined Cards will only have one of them - final List objects = AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam("Defined"), sa); + final List objects = AbilityUtils.getDefinedObjects(hostCard, sa.getParam("Defined"), sa); // react to threats on the stack if (!game.getStack().isEmpty()) { @@ -138,7 +138,7 @@ public class DamagePreventAi extends SpellAbilityAi { } } if (sa.usesTargeting() && sa.isDividedAsYouChoose() && !sa.getTargets().isEmpty()) { - sa.addDividedAllocation(sa.getTargets().get(0), AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa)); + sa.addDividedAllocation(sa.getTargets().get(0), AbilityUtils.calculateAmount(hostCard, sa.getParam("Amount"), sa)); } return chance; 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 f4c63e06b8f..4d95e1a15eb 100644 --- a/forge-ai/src/main/java/forge/ai/ability/GoadAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/GoadAi.java @@ -39,6 +39,10 @@ public class GoadAi extends SpellAbilityAi { if (ComputerUtilCard.isUselessCreature(ai, c)) { return false; } + // useless + if (c.isGoadedBy(ai)) { + return false; + } // select creatures which can attack an Opponent other than ai for (Player o : ai.getOpponents()) { if (ComputerUtilCombat.canAttackNextTurn(c, o)) { @@ -64,6 +68,10 @@ public class GoadAi extends SpellAbilityAi { if (ComputerUtilCard.isUselessCreature(ai, c)) { return false; } + // useless + if (c.isGoadedBy(ai)) { + return false; + } // select only creatures AI can block return ComputerUtilCard.canBeBlockedProfitably(ai, c, false); } diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 4416787a829..d07fcafaf9c 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -1939,7 +1939,6 @@ public class GameAction { public void startGame(GameOutcome lastGameOutcome) { startGame(lastGameOutcome, null); } - public void startGame(GameOutcome lastGameOutcome, Runnable startGameHook) { Player first = determineFirstTurnPlayer(lastGameOutcome); 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 1620fcf3cf9..ab1b0f333e9 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -992,12 +992,17 @@ public class AbilityUtils { */ public static PlayerCollection getDefinedPlayers(final Card card, final String def, final CardTraitBase sa) { final PlayerCollection players = new PlayerCollection(); - final String defined = (def == null) ? "You" : applyAbilityTextChangeEffects(def, sa); + String changedDef = (def == null) ? "You" : applyAbilityTextChangeEffects(def, sa); // default to Self + final String[] incR = changedDef.split("\\.", 2); + String defined = incR[0]; + final Game game = card == null ? null : card.getGame(); final Player player = sa instanceof SpellAbility ? ((SpellAbility)sa).getActivatingPlayer() : card.getController(); - if (defined.equals("TargetedOrController")) { + if (defined.equals("Self")) { + // do nothing, Self is for Cards, not Players + } else if (defined.equals("TargetedOrController")) { players.addAll(getDefinedPlayers(card, "Targeted", sa)); players.addAll(getDefinedPlayers(card, "TargetedController", sa)); } @@ -1056,6 +1061,15 @@ public class AbilityUtils { else if (defined.startsWith("Remembered")) { addPlayer(card.getRemembered(), defined, players); } + else if (defined.startsWith("Imprinted")) { + addPlayer(Lists.newArrayList(card.getImprintedCards()), defined, players); + } + else if (defined.startsWith("EffectSource")) { + Card root = findEffectRoot(card); + if (root != null) { + addPlayer(Lists.newArrayList(root), defined, players); + } + } else if (defined.startsWith("DelayTriggerRemembered") && sa instanceof SpellAbility) { SpellAbility root = ((SpellAbility)sa).getRootAbility(); if (root != null) { @@ -1064,16 +1078,6 @@ public class AbilityUtils { System.err.println("Warning: couldn't find trigger SA in the chain of SpellAbility " + sa); } } - else if (defined.equals("ImprintedController")) { - for (final Card rem : card.getImprintedCards()) { - players.add(rem.getController()); - } - } - else if (defined.equals("ImprintedOwner")) { - for (final Card rem : card.getImprintedCards()) { - players.add(rem.getOwner()); - } - } else if (defined.startsWith("Triggered") && sa instanceof SpellAbility) { String defParsed = defined.endsWith("AndYou") ? defined.substring(0, defined.indexOf("AndYou")) : defined; if (defined.endsWith("AndYou")) { @@ -1124,7 +1128,7 @@ public class AbilityUtils { } } else { - final String triggeringType = defParsed.substring(9); + String triggeringType = defParsed.substring(9); o = root.getTriggeringObject(AbilityKey.fromString(triggeringType)); } if (o != null) { @@ -1176,29 +1180,26 @@ public class AbilityUtils { players.addAll(game.getPlayersInTurnOrder()); players.removeAll((FCollectionView)getDefinedPlayers(card, defined.substring(3), sa)); } - else if (defined.equals("EnchantedController")) { - if (card.getEnchantingCard() == null) { - return players; - } - players.add(card.getEnchantingCard().getController()); - } - else if (defined.equals("EnchantedOwner")) { - if (card.getEnchantingCard() == null) { - return players; - } - players.add(card.getEnchantingCard().getOwner()); - } else if (defined.equals("EnchantedPlayer")) { final Object o = sa.getHostCard().getEntityAttachedTo(); if (o instanceof Player) { players.add((Player) o); } } - else if (defined.equals("AttackingPlayer")) { - if (!game.getPhaseHandler().inCombat()) { - return players; + else if (defined.startsWith("Enchanted")) { + if (card.getEntityAttachedTo() != null) { + addPlayer(Lists.newArrayList(card.getEntityAttachedTo()), defined, players); + } + } + else if (defined.startsWith("Equipped")) { + if (card.getEquipping() != null) { + addPlayer(Lists.newArrayList(card.getEquipping()), defined, players); + } + } + else if (defined.equals("AttackingPlayer")) { + if (game.getPhaseHandler().inCombat()) { + players.add(game.getCombat().getAttackingPlayer()); } - players.add(game.getCombat().getAttackingPlayer()); } else if (defined.equals("DefendingPlayer")) { players.add(game.getCombat().getDefendingPlayerRelatedTo(card)); @@ -1250,8 +1251,10 @@ public class AbilityUtils { } } } - else if (defined.equals("Caster") && sa.getHostCard().wasCast()) { - players.add((sa.getHostCard().getCastSA().getActivatingPlayer())); + else if (defined.equals("Caster")) { + if (sa.getHostCard().wasCast()) { + players.add((sa.getHostCard().getCastSA().getActivatingPlayer())); + } } else if (defined.equals("ActivePlayer")) { players.add(game.getPhaseHandler().getPlayerTurn()); @@ -1267,11 +1270,17 @@ public class AbilityUtils { players.add(game.getNextPlayerAfter(player, dir)); } else { - for (Player p : game.getPlayersInTurnOrder()) { - if (p.isValid(defined, player, card, sa)) { - players.add(p); - } + // will be filtered below + players.addAll(game.getPlayersInTurnOrder()); + } + + if (incR.length > 1 && !players.isEmpty()) { + String[] valids = incR[1].split(","); + // need to add valids onto all of them + for (int i = 0; i < valids.length; i++) { + valids[i] = "Player." + valids[i]; } + return players.filter(PlayerPredicates.restriction(valids, player, card, sa)); } return players; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChooseGenericEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChooseGenericEffect.java index 7fc21484e63..2a8bff2a550 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChooseGenericEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChooseGenericEffect.java @@ -72,7 +72,7 @@ public class ChooseGenericEffect extends SpellAbilityEffect { if (sa.hasParam("AtRandom")) { random = true; Aggregates.random(abilities, amount, chosenSAs); - } else { + } else if (!abilities.isEmpty()) { chosenSAs = p.getController().chooseSpellAbilitiesForEffect(abilities, sa, prompt, amount, ImmutableMap.of()); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java index 252cd54c799..7a04a7b5a2f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java @@ -476,10 +476,10 @@ public class CountersPutEffect extends SpellAbilityEffect { // these trigger are one per counter for (int i = 0; i < added; i++) { - final Trigger trig = TriggerHandler.parseTrigger(delTrig.toString(), sa.getHostCard(), intrinsic); + final Trigger trig = TriggerHandler.parseTrigger(delTrig.toString(), host, intrinsic); trig.addRemembered(tgt); - final SpellAbility newSa = AbilityFactory.getAbility(trigSA, sa.getHostCard()); + final SpellAbility newSa = AbilityFactory.getAbility(trigSA, host); newSa.setIntrinsic(intrinsic); trig.setOverridingAbility(newSa); sa.getActivatingPlayer().getGame().getTriggerHandler().registerDelayedTrigger(trig); diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java index fb80153cbd8..bf99ae74127 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java @@ -79,7 +79,7 @@ public class CountersRemoveAllEffect extends SpellAbilityEffect { } } if (sa.hasParam("RememberAmount")) { - sa.getHostCard().setChosenNumber(numberRemoved); + sa.getHostCard().addRemembered(Integer.valueOf(numberRemoved)); } } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/GoadEffect.java b/forge-game/src/main/java/forge/game/ability/effects/GoadEffect.java index 3080170b353..8e771b41b26 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/GoadEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/GoadEffect.java @@ -27,6 +27,7 @@ public class GoadEffect extends SpellAbilityEffect { continue; } + // 701.38d is handled by getGoaded tgtC.addGoad(timestamp, player); final GameCommand untilEOT = new GameCommand() { diff --git a/forge-game/src/main/java/forge/game/ability/effects/MustAttackEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MustAttackEffect.java index 16eb26c3bd5..586e01158d0 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MustAttackEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MustAttackEffect.java @@ -67,9 +67,10 @@ public class MustAttackEffect extends SpellAbilityEffect { } } + // TODO these should not override but add another requirement for (final Player p : tgtPlayers) { if ((tgt == null) || p.canBeTargetedBy(sa)) { - if (thisTurn) { + if (thisTurn || !p.getGame().getPhaseHandler().isPlayerTurn(p)) { p.setMustAttackEntityThisTurn(entity); } else { p.setMustAttackEntity(entity); diff --git a/forge-game/src/main/java/forge/game/ability/effects/MustBlockEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MustBlockEffect.java index 0554eeb3d01..214cf97fb1d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MustBlockEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MustBlockEffect.java @@ -65,7 +65,6 @@ public class MustBlockEffect extends SpellAbilityEffect { } else { final Card attacker = cards.get(0); c.addMustBlockCard(attacker); - System.out.println(c + " is adding " + attacker + " to mustBlockCards: " + c.getMustBlockCards()); } } } 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 0a05a9ec7d3..8af4089cd9c 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -3474,6 +3474,13 @@ public class Card extends GameEntity implements Comparable, IHasSVars { runUnattachCommands(); } + public final boolean isModified() { + if (this.isEquipped() || this.hasCounters()) { + return true; + } + return Iterables.any(this.getEnchantedBy(), CardPredicates.isController(this.getController())); + } + public final void setType(final CardType type0) { currentState.setType(type0); } @@ -5419,6 +5426,11 @@ public class Card extends GameEntity implements Comparable, IHasSVars { damageType = DamageType.Deathtouch; } + // 704.8: if it looks like the creature might die from SBA make sure the LKI is refreshed + if (hasBeenDealtDeathtouchDamage() || (getDamage() > 0 && getLethal() <= getDamage())) { + game.updateLastStateForCard(this); + } + // Play the Damage sound game.fireEvent(new GameEventCardDamaged(this, source, damageIn, damageType)); } @@ -6588,8 +6600,8 @@ public class Card extends GameEntity implements Comparable, IHasSVars { return goad.containsValue(p); } - public final Collection getGoaded() { - return goad.values(); + public final PlayerCollection getGoaded() { + return new PlayerCollection(goad.values()); // 701.38d } /** 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 8a250aa9063..c21628ea5b0 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -852,9 +852,6 @@ public class CardFactoryUtil { String pumpStr = "DB$ Pump | Defined$ Self | NumAtt$ " + n + " | NumDef$ " + n; SpellAbility pump = AbilityFactory.getAbility(pumpStr, card); - if ("X".equals(n)) { - pump.setSVar("X", "Count$Valid Creature.attacking"); - } final Trigger bushidoTrigger1 = TriggerHandler.parseTrigger(trigBlock, card, intrinsic); final Trigger bushidoTrigger2 = TriggerHandler.parseTrigger(trigBlocked, card, intrinsic); @@ -1480,7 +1477,7 @@ public class CardFactoryUtil { "TgtPrompt$ Select target artifact creature | CounterType$ P1P1 | CounterNum$ ModularX | Modular$ True"; String trigStr = "Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard" + - " | OptionalDecider$ TriggeredCardController | TriggerController$ TriggeredCardController" + + " | OptionalDecider$ TriggeredCardController" + " | Secondary$ True | TriggerDescription$ When CARDNAME dies, " + "you may put a +1/+1 counter on target artifact creature for each +1/+1 counter on CARDNAME"; @@ -1787,16 +1784,11 @@ public class CardFactoryUtil { final String actualTrigger = "Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard" + "| Secondary$ True | OptionalDecider$ You | ValidCard$ Card.Self" - + "| TriggerController$ TriggeredCardController | TriggerDescription$ " + k[0] + " " + k[1] - + " (" + inst.getReminderText() + ")"; + + "| TriggerDescription$ " + k[0] + " " + k[1] + " (" + inst.getReminderText() + ")"; final String effect = "DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand" + "| ValidTgts$ Spirit.YouOwn+cmcLE" + k[1]; final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, card, intrinsic); final SpellAbility sp = AbilityFactory.getAbility(effect, card); - // Soulshift X - if (k[1].equals("X")) { - sp.setSVar("X", "Count$LastStateBattlefield " + k[3]); - } parsedTrigger.setOverridingAbility(sp); @@ -2004,8 +1996,8 @@ public class CardFactoryUtil { + " | TriggerDescription$ If you cast it any time a sorcery couldn't have been cast, " + " the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step."; - final String strDelay = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Cleanup | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME."; - final String strSac = "DB$ SacrificeAll | Defined$ Self"; + final String strDelay = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Cleanup | RememberObjects$ Self | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME."; + final String strSac = "DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI"; SpellAbility saDelay = AbilityFactory.getAbility(strDelay, card); saDelay.setAdditionalAbility("Execute", (AbilitySub) AbilityFactory.getAbility(strSac, card)); diff --git a/forge-game/src/main/java/forge/game/card/CardPredicates.java b/forge-game/src/main/java/forge/game/card/CardPredicates.java index 201eb8b0a57..b13b9ab0adc 100644 --- a/forge-game/src/main/java/forge/game/card/CardPredicates.java +++ b/forge-game/src/main/java/forge/game/card/CardPredicates.java @@ -228,7 +228,7 @@ public final class CardPredicates { return new Predicate() { @Override public boolean apply(final Card c) { - return (c != null) && c.isValid(restrictions, sourceController, source, spellAbility); + return c != null && c.isValid(restrictions, sourceController, source, spellAbility); } }; } @@ -237,7 +237,7 @@ public final class CardPredicates { return new Predicate() { @Override public boolean apply(final Card c) { - return (c != null) && c.isValid(restrictions, sourceController, source, spellAbility); + return c != null && c.isValid(restrictions, sourceController, source, spellAbility); } }; } 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 6240b39d65d..b977a433fd6 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -1328,6 +1328,10 @@ public class CardProperty { if (card.isEquipping()) { return false; } + } else if (property.startsWith("modified")) { + if (!card.isModified()) { + return false; + } } else if (property.startsWith("token")) { if (!card.isToken() && !card.isTokenCard()) { return false; 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 4d639a0d8e9..ddc6101eaa2 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 @@ -263,7 +263,7 @@ public class TokenInfo { } static public Card getProtoType(final String script, final SpellAbility sa, final Player owner) { - return getProtoType(script, sa, owner, true); + return getProtoType(script, sa, owner, !sa.hasParam("LockTokenScript")); } static public Card getProtoType(final String script, final SpellAbility sa, final Player owner, boolean applyTextChange) { // script might be null, or sa might be null diff --git a/forge-game/src/main/java/forge/game/combat/AttackRequirement.java b/forge-game/src/main/java/forge/game/combat/AttackRequirement.java index 6da720bdc43..9ad0ca64658 100644 --- a/forge-game/src/main/java/forge/game/combat/AttackRequirement.java +++ b/forge-game/src/main/java/forge/game/combat/AttackRequirement.java @@ -35,10 +35,6 @@ public class AttackRequirement { this.causesToAttack = causesToAttack; - final GameEntity mustAttack = attacker.getController().getMustAttackEntity(); - if (mustAttack != null) { - defenderSpecific.add(mustAttack); - } final GameEntity mustAttackThisTurn = attacker.getController().getMustAttackEntityThisTurn(); if (mustAttackThisTurn != null) { defenderSpecific.add(mustAttackThisTurn); @@ -47,6 +43,7 @@ public class AttackRequirement { int nAttackAnything = 0; if (attacker.isGoaded()) { + // Goad has two requirements but the other is handled by CombatUtil currently nAttackAnything += attacker.getGoaded().size(); } @@ -70,11 +67,7 @@ public class AttackRequirement { nAttackAnything++; } } - - final GameEntity mustAttack3 = attacker.getMustAttackEntity(); - if (mustAttack3 != null) { - defenderSpecific.add(mustAttack3); - } + final GameEntity mustAttackThisTurn3 = attacker.getMustAttackEntityThisTurn(); if (mustAttackThisTurn3 != null) { defenderSpecific.add(mustAttackThisTurn3); 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 990cbb799e2..8c0cad57405 100644 --- a/forge-game/src/main/java/forge/game/cost/CostReveal.java +++ b/forge-game/src/main/java/forge/game/cost/CostReveal.java @@ -72,7 +72,7 @@ public class CostReveal extends CostPartWithList { modifiedHand.remove(source); // can't pay for itself handList = modifiedHand; } - handList = CardLists.getValidCards(handList, getType().split(","), payer, source, ability); + handList = CardLists.getValidCards(handList, getType(), payer, source, ability); return handList.size(); } 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 fa4e6b36b6e..e5e357034bb 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -825,6 +825,7 @@ public class PhaseHandler implements java.io.Serializable { private Player handleNextTurn() { game.getStack().onNextTurn(); // reset mustAttackEntity + playerTurn.setMustAttackEntityThisTurn(playerTurn.getMustAttackEntity()); playerTurn.setMustAttackEntity(null); game.getTriggerHandler().clearThisTurnDelayedTrigger(); diff --git a/forge-game/src/main/java/forge/game/phase/PhaseType.java b/forge-game/src/main/java/forge/game/phase/PhaseType.java index 7bb60d98830..1e33f557fa7 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseType.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseType.java @@ -116,8 +116,7 @@ public enum PhaseType { String sTo = s.substring(idxArrow + 2); PhaseType to = StringUtils.isBlank(sTo) ? PhaseType.CLEANUP : PhaseType.smartValueOf(sTo); result.addAll(EnumSet.range(from, to)); - } - else { + } else { result.add(PhaseType.smartValueOf(s)); } } diff --git a/forge-game/src/main/java/forge/game/player/PlayerPredicates.java b/forge-game/src/main/java/forge/game/player/PlayerPredicates.java index 021a6ce959f..049550ddf55 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerPredicates.java +++ b/forge-game/src/main/java/forge/game/player/PlayerPredicates.java @@ -5,6 +5,7 @@ import java.util.Comparator; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import forge.game.CardTraitBase; import forge.game.card.Card; import forge.game.card.CardLists; import forge.game.card.CounterEnumType; @@ -129,6 +130,15 @@ public final class PlayerPredicates { }; } + public static final Predicate restriction(final String[] restrictions, final Player sourceController, final Card source, final CardTraitBase spellAbility) { + return new Predicate() { + @Override + public boolean apply(final Player c) { + return c != null && c.isValid(restrictions, sourceController, source, spellAbility); + } + }; + } + public static final Comparator compareByZoneSize(final ZoneType zone) { return new Comparator() { @Override 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 6ab02f7e9a0..62dfd5e99d6 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -306,6 +306,9 @@ public final class StaticAbilityContinuous { input = input.replaceAll("chosenEvenOdd", hostCard.getChosenEvenOdd().toString().toLowerCase()); } input = input.replace("HostCardUID", hostCardUID); + if (params.containsKey("CalcKeywordN")) { + input = input.replace("N", String.valueOf(AbilityUtils.calculateAmount(hostCard, params.get("CalcKeywordN"), stAb))); + } return input; } @@ -867,7 +870,7 @@ public final class StaticAbilityContinuous { // but only do it if the trigger doesn't already have a overriding ability addedTrigger.add(actualTrigger); if (params.containsKey("TriggerRememberDefined")) { - String triggerRemembered = (params.get("TriggerRememberDefined")); + String triggerRemembered = params.get("TriggerRememberDefined"); for (final String rem : triggerRemembered.split(",")) { for (final Object o : AbilityUtils.getDefinedEntities(hostCard, rem, stAb)) { actualTrigger.addRemembered(o); @@ -903,7 +906,7 @@ public final class StaticAbilityContinuous { } // add Types - if ((addTypes != null) || (removeTypes != null) || addAllCreatureTypes + if (addTypes != null || removeTypes != null || addAllCreatureTypes || removeSuperTypes || removeCardTypes || removeLandTypes || removeCreatureTypes || removeArtifactTypes || removeEnchantmentTypes) { affectedCard.addChangedCardTypes(addTypes, removeTypes, addAllCreatureTypes, removeSuperTypes, removeCardTypes, removeSubTypes, removeLandTypes, removeCreatureTypes, removeArtifactTypes, removeEnchantmentTypes, diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityIgnoreHexproofShroud.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityIgnoreHexproofShroud.java index 6a28d3df47d..b0a12c9a157 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityIgnoreHexproofShroud.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityIgnoreHexproofShroud.java @@ -17,15 +17,15 @@ public class StaticAbilityIgnoreHexproofShroud { final Game game = entity.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 (keyword.equals(Keyword.HEXPROOF) && !stAb.getParam("Mode").equals(HEXPROOF_MODE)) { continue; } if (keyword.equals(Keyword.SHROUD) && !stAb.getParam("Mode").equals(SHROUD_MODE)) { continue; } + if (stAb.isSuppressed() || !stAb.checkConditions()) { + continue; + } if (commonAbility(stAb, entity, spellAbility)) { return true; } diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index 9c2f582d73d..bc61db98f31 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -7,6 +7,8 @@ import java.util.List; import java.util.Map; import forge.ai.GameState; +import forge.deck.Deck; +import forge.game.player.Player; import forge.item.IPaperCard; import org.apache.commons.lang3.StringUtils; @@ -94,14 +96,26 @@ public class MatchController extends AbstractGuiGame { } } + public static Deck getPlayerDeck(final PlayerView playerView) { + try { + for (Player p : instance.getGameView().getGame().getPlayers()) { + if (p.getView() == playerView) { + return p.getRegisteredPlayer().getDeck(); + } + } + } catch (Exception e) { + return null; + } + return null; + } + public static FImage getPlayerAvatar(final PlayerView p) { final String lp = p.getLobbyPlayerName(); FImage avatar = avatarImages.get(lp); if (avatar == null) { if (StringUtils.isEmpty(p.getAvatarCardImageKey())) { avatar = new FTextureRegionImage(FSkin.getAvatars().get(p.getAvatarIndex())); - } - else { //handle lobby players with art from cards + } else { //handle lobby players with art from cards avatar = new CardAvatarImage(p.getAvatarCardImageKey()); } } diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index 1fbc54c30be..c97552706dd 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -354,26 +354,24 @@ public class MatchScreen extends FScreen { final GameView game = MatchController.instance.getGameView(); if (game == null) { return; } - if(gameMenu!=null) { - if(gameMenu.getChildCount()>3){ - if(viewWinLose == null) { + if (gameMenu!=null) { + if (gameMenu.getChildCount()>2){ + if (viewWinLose == null) { gameMenu.getChildAt(0).setEnabled(!game.isMulligan()); gameMenu.getChildAt(1).setEnabled(!game.isMulligan()); gameMenu.getChildAt(2).setEnabled(!game.isMulligan()); - gameMenu.getChildAt(3).setEnabled(!game.isMulligan()); - gameMenu.getChildAt(4).setEnabled(false); + gameMenu.getChildAt(3).setEnabled(false); } else { gameMenu.getChildAt(0).setEnabled(false); gameMenu.getChildAt(1).setEnabled(false); gameMenu.getChildAt(2).setEnabled(false); - gameMenu.getChildAt(3).setEnabled(false); - gameMenu.getChildAt(4).setEnabled(true); + gameMenu.getChildAt(3).setEnabled(true); } } } - if(devMenu!=null) { - if(devMenu.isVisible()){ - if(viewWinLose == null) + if (devMenu!=null) { + if (devMenu.isVisible()){ + if (viewWinLose == null) devMenu.setEnabled(true); else devMenu.setEnabled(false); diff --git a/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java b/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java index 4dc39a93b69..a0e06cb7c0e 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java @@ -2,16 +2,12 @@ package forge.screens.match.views; import forge.Forge; import forge.assets.FSkinImage; -import forge.deck.Deck; -import forge.deck.FDeckViewer; -import forge.game.player.Player; import forge.menu.FDropDownMenu; import forge.menu.FMenuItem; import forge.screens.match.MatchController; import forge.screens.settings.SettingsScreen; import forge.toolbox.FEvent; import forge.toolbox.FEvent.FEventHandler; -import forge.toolbox.FOptionPane; import forge.util.Localizer; import forge.util.ThreadUtil; @@ -47,26 +43,6 @@ public class VGameMenu extends FDropDownMenu { GameStateDeserializer.loadGameState(MatchUtil.getGame(), ForgeConstants.USER_GAMES_DIR + "GameSave.txt"); } }));*/ - addItem(new FMenuItem(localizer.getMessage("lblDeckList"), FSkinImage.DECKLIST, new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - //pause game when spectating AI Match - if (!MatchController.instance.hasLocalPlayers()) { - if(!MatchController.instance.isGamePaused()) - MatchController.instance.pauseMatch(); - } - - final Player player = MatchController.getHostedMatch().getGame().getPhaseHandler().getPlayerTurn(); - if (player != null) { - final Deck deck = player.getRegisteredPlayer().getDeck(); - if (deck != null) { - FDeckViewer.show(deck); - return; - } - } - FOptionPane.showMessageDialog(localizer.getMessage("lblNoPlayerPriorityNoDeckListViewed")); - } - })); addItem(new FMenuItem(localizer.getMessage("lblAutoYields"), Forge.hdbuttons ? FSkinImage.HDYIELD : FSkinImage.WARNING, new FEventHandler() { @Override public void handleEvent(FEvent e) { diff --git a/forge-gui-mobile/src/forge/screens/match/views/VPlayers.java b/forge-gui-mobile/src/forge/screens/match/views/VPlayers.java index b74a3e9dcfa..6ef11194ca6 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VPlayers.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VPlayers.java @@ -2,14 +2,19 @@ package forge.screens.match.views; import com.badlogic.gdx.utils.Align; +import forge.Forge; import forge.Graphics; -import forge.assets.FImage; import forge.assets.FSkinFont; +import forge.assets.FSkinImage; +import forge.deck.Deck; +import forge.deck.FDeckViewer; import forge.game.player.PlayerView; import forge.menu.FDropDown; import forge.screens.match.MatchController; import forge.toolbox.FContainer; import forge.toolbox.FDisplayObject; +import forge.toolbox.FEvent; +import forge.toolbox.FLabel; import forge.toolbox.FList; import forge.util.Utils; @@ -42,14 +47,38 @@ public class VPlayers extends FDropDown { private static final float PADDING = Utils.scale(5); private static final float HEIGHT = Utils.AVG_FINGER_HEIGHT * 1.8f; private final PlayerView player; + private final Deck playerDeck; + private final FLabel btnDeck; + private boolean btnAdded = false; private PlayerInfoPanel(PlayerView player0) { player = player0; + playerDeck = MatchController.getPlayerDeck(player0); + btnDeck = new FLabel.ButtonBuilder().opaque(true).iconScaleFactor(0.99f).selectable().alphaComposite(1).iconInBackground(true).build(); + btnDeck.setCommand(new FEvent.FEventHandler() { + @Override + public void handleEvent(FEvent e) { + if (playerDeck != null) { + //pause game when spectating AI Match + if (!MatchController.instance.hasLocalPlayers()) { + if(!MatchController.instance.isGamePaused()) + MatchController.instance.pauseMatch(); + } + FDeckViewer.show(playerDeck); + } + } + }); } @Override protected void doLayout(float width, float height) { - //TODO: Add FLabels to click to select player in top or bottom panel of Match screen + if (!btnAdded) { + btnDeck.setBounds(PADDING, PADDING, getHeight() - 2 * PADDING, getHeight() - 2 * PADDING); + btnDeck.setIcon(MatchController.getPlayerAvatar(player)); + btnDeck.setOverlayIcon(Forge.hdbuttons ? FSkinImage.HDSEARCH : FSkinImage.SEARCH); + add(btnDeck); + btnAdded = true; + } } @Override @@ -57,12 +86,9 @@ public class VPlayers extends FDropDown { float x = PADDING; float y = PADDING; float h = getHeight() - 2 * y; - - FImage avatarImage = MatchController.getPlayerAvatar(player); - g.drawImage(avatarImage, x, y, h, h); x += h + PADDING; - - g.drawText(player.getDetails(), FONT, FList.FORE_COLOR, x, y, getWidth() - PADDING - x, h, true, Align.left, true); + //Draw Player Details + g.drawText(player.getDetails() + playerDeck.getName(), FONT, FList.FORE_COLOR, x, y, getWidth() - PADDING - x, h, true, Align.left, true); } @Override diff --git a/forge-gui-mobile/src/forge/toolbox/FLabel.java b/forge-gui-mobile/src/forge/toolbox/FLabel.java index 5cf2287d0ca..a48b09c9b6c 100644 --- a/forge-gui-mobile/src/forge/toolbox/FLabel.java +++ b/forge-gui-mobile/src/forge/toolbox/FLabel.java @@ -9,6 +9,7 @@ import forge.assets.FImage; import forge.assets.FSkinColor; import forge.assets.FSkinColor.Colors; import forge.assets.FSkinFont; +import forge.assets.FSkinImage; import forge.assets.TextRenderer; import forge.gui.UiCommand; import forge.gui.interfaces.IButton; @@ -110,6 +111,7 @@ public class FLabel extends FDisplayObject implements IButton { private String text; private FImage icon; + private FSkinImage overlayIcon; private FSkinColor textColor, pressedColor; private FEventHandler command; private TextRenderer textRenderer; @@ -172,6 +174,9 @@ public class FLabel extends FDisplayObject implements IButton { public void setIcon(final FImage icon0) { icon = icon0; } + public void setOverlayIcon(final FSkinImage overlayIcon0) { + overlayIcon = overlayIcon0; + } public boolean getIconScaleAuto() { return iconScaleAuto; @@ -321,81 +326,95 @@ public class FLabel extends FDisplayObject implements IButton { } protected void drawContent(Graphics g, float x, float y, float w, float h) { - if (icon != null) { - float textY = y; - float iconWidth = icon.getWidth(); - float iconHeight = icon.getHeight(); - float aspectRatio = iconWidth / iconHeight; + try { + if (icon != null) { + float textY = y; + float iconWidth = icon.getWidth(); + float iconHeight = icon.getHeight(); + float aspectRatio = iconWidth / iconHeight; - if (iconScaleWithFont) { - iconHeight = font.getLineHeight() * iconScaleFactor; - iconWidth = iconHeight * aspectRatio; - } - else if (iconInBackground || iconScaleAuto) { - iconHeight = h * iconScaleFactor; - iconWidth = iconHeight * aspectRatio; - if (iconWidth > w && iconInBackground) { //ensure background icon stays with label bounds - iconWidth = w; - iconHeight = iconWidth / aspectRatio; + if (iconScaleWithFont) { + iconHeight = font.getLineHeight() * iconScaleFactor; + iconWidth = iconHeight * aspectRatio; } - } - - float iconOffset = iconWidth + insets.x + getExtraGapBetweenIconAndText(); - - if (iconInBackground || text.isEmpty()) { - if (alignment == Align.center) { - x += (w - iconWidth) / 2; - } - y += (h - iconHeight) / 2; - } - else { - if (alignment == Align.center) { - float dx; - while (true) { - dx = (w - iconOffset - getTextWidth()) / 2; - if (dx > 0) { - x += dx; - break; - } - if (!font.canShrink()) { - break; - } - font = font.shrink(); + else if (iconInBackground || iconScaleAuto) { + iconHeight = h * iconScaleFactor; + iconWidth = iconHeight * aspectRatio; + if (iconWidth > w && iconInBackground) { //ensure background icon stays with label bounds + iconWidth = w; + iconHeight = iconWidth / aspectRatio; } } - else if (alignment == Align.right) { - float dx; - while (true) { - dx = (w - iconWidth - getTextWidth() - insets.x); - if (dx > 0) { - x += dx; - break; - } - if (!font.canShrink()) { - break; - } - font = font.shrink(); - } - } - y += (h - iconHeight) / 2; - } - float mod = isHovered() && selectable ? iconWidth < iconHeight ? iconWidth/8f : iconHeight/8f : 0; - g.drawImage(icon, x-mod/2, y-mod/2, iconWidth+mod, iconHeight+mod); - if (!text.isEmpty()) { - x += iconOffset; - w -= iconOffset; - drawText(g, x, textY, w, h, Align.left); + float iconOffset = iconWidth + insets.x + getExtraGapBetweenIconAndText(); + + if (iconInBackground || text.isEmpty()) { + if (alignment == Align.center) { + x += (w - iconWidth) / 2; + } + y += (h - iconHeight) / 2; + } + else { + if (alignment == Align.center) { + float dx; + while (true) { + dx = (w - iconOffset - getTextWidth()) / 2; + if (dx > 0) { + x += dx; + break; + } + if (!font.canShrink()) { + break; + } + font = font.shrink(); + } + } + else if (alignment == Align.right) { + float dx; + while (true) { + dx = (w - iconWidth - getTextWidth() - insets.x); + if (dx > 0) { + x += dx; + break; + } + if (!font.canShrink()) { + break; + } + font = font.shrink(); + } + } + y += (h - iconHeight) / 2; + } + float mod = isHovered() && selectable ? iconWidth < iconHeight ? iconWidth/8f : iconHeight/8f : 0; + //draw icon + g.drawImage(icon, x-mod/2, y-mod/2, iconWidth+mod, iconHeight+mod); + //draw overlay + if (overlayIcon != null) { + float oldAlpha = g.getfloatAlphaComposite(); + float overlayWidth = isHovered() ? iconWidth/2.5f : iconWidth/3.5f; + float overlayHeight = isHovered() ? iconHeight/2.5f : iconHeight/3.5f; + if (!isHovered()) + g.setAlphaComposite(0.4f); + g.drawImage(overlayIcon, iconWidth-overlayWidth+mod, iconHeight-overlayHeight+mod, overlayWidth, overlayHeight); + g.setAlphaComposite(oldAlpha); + } + if (!text.isEmpty()) { + x += iconOffset; + w -= iconOffset; + drawText(g, x, textY, w, h, Align.left); + } } - } - else if (!text.isEmpty()) { - float oldAlpha = g.getfloatAlphaComposite(); - if (isHovered() && selectable) { - g.setAlphaComposite(0.4f); - g.fillRect(Color.GRAY, x, y, w, h); - g.setAlphaComposite(oldAlpha); + else if (!text.isEmpty()) { + float oldAlpha = g.getfloatAlphaComposite(); + if (isHovered() && selectable) { + g.setAlphaComposite(0.4f); + g.fillRect(Color.GRAY, x, y, w, h); + g.setAlphaComposite(oldAlpha); + } + drawText(g, x, y, w, h, alignment); } - drawText(g, x, y, w, h, alignment); + } catch (Exception e) { + e.printStackTrace(); } } diff --git a/forge-gui/res/cardsfolder/a/assemble_from_parts.txt b/forge-gui/res/cardsfolder/a/assemble_from_parts.txt index 9700321209f..a7abc37a388 100644 --- a/forge-gui/res/cardsfolder/a/assemble_from_parts.txt +++ b/forge-gui/res/cardsfolder/a/assemble_from_parts.txt @@ -1,10 +1,10 @@ Name:Assemble from Parts ManaCost:B Types:Instant -A:SP$ Effect | TgtZone$ Graveyard | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select target creature card in your graveyard | StaticAbilities$ Assembly | RememberObjects$ Targeted | Name$ Assemble from Part's Perpetual Effect | Duration$ Permanent | StackDescription$ {c:Targeted} perpetually gains "{3} {B}, Exile this card from your graveyard: Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery." | SpellDescription$ Target creature card in your graveyard perpetually gains "{3} {B}, Exile this card from your graveyard: Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery." -SVar:Assembly:Mode$ Continuous | Affected$ Card.IsRemembered | AddAbility$ ABShuffle | EffectZone$ Command | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | Description$ Target creature card in your graveyard perpetually gains "{3} {B}, Exile this card from your graveyard: Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery." -SVar:ABShuffle:AB$ ChangeZone | Cost$ 3 B ExileFromGrave<1/CARDNAME> | ActivationZone$ Graveyard | Origin$ All | Destination$ Library | Shuffle$ True | Defined$ Self | SubAbility$ DBCopy | SorcerySpeed$ True | StackDescription$ Shuffle CARDNAME into your library. | SpellDescription$ Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery. +A:SP$ Effect | TgtZone$ Graveyard | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select target creature card in your graveyard | StaticAbilities$ Assembly | RememberObjects$ Targeted | Name$ Assemble from Part's Perpetual Effect | Duration$ Permanent | StackDescription$ {c:Targeted} perpetually gains "{3} {B}, Exile this card from your graveyard: Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery." | SpellDescription$ Target creature card in your graveyard perpetually gains "{1}{B}{B}, Exile this card from your graveyard: Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery." +SVar:Assembly:Mode$ Continuous | Affected$ Card.IsRemembered | AddAbility$ ABShuffle | EffectZone$ Command | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | Description$ Target creature card in your graveyard perpetually gains "{1}{B}{B}, Exile this card from your graveyard: Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery." +SVar:ABShuffle:AB$ ChangeZone | Cost$ 1 B B ExileFromGrave<1/CARDNAME> | ActivationZone$ Graveyard | Origin$ All | Destination$ Library | Shuffle$ True | Defined$ Self | SubAbility$ DBCopy | SorcerySpeed$ True | StackDescription$ Shuffle CARDNAME into your library. | SpellDescription$ Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery. SVar:DBCopy:DB$ CopyPermanent | Defined$ Self | SetPower$ 4 | SetToughness$ 4 | AddTypes$ Zombie | SetColor$ Black | StackDescription$ Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. SVar:AIPreference:ExileFromGraveCost$Creature.YouOwn+inZoneGraveyard DeckHas:Ability$Token & Ability$Graveyard -Oracle:Target creature card in your graveyard perpetually gains "{3} {B}, Exile this card from your graveyard: Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery." +Oracle:Target creature card in your graveyard perpetually gains "{1}{B}{B}, Exile this card from your graveyard: Shuffle it into your library. Create a token that's a copy of it, except it's a 4/4 black Zombie in addition to its other types. Activate only as a sorcery." diff --git a/forge-gui/res/cardsfolder/a/avalanche_tusker.txt b/forge-gui/res/cardsfolder/a/avalanche_tusker.txt index df65f8bb3af..8373d40fa42 100644 --- a/forge-gui/res/cardsfolder/a/avalanche_tusker.txt +++ b/forge-gui/res/cardsfolder/a/avalanche_tusker.txt @@ -2,7 +2,6 @@ Name:Avalanche Tusker ManaCost:2 G U R Types:Creature Elephant Warrior PT:6/4 -T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigCantBlock | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, target creature defending player controls blocks this combat if able. -SVar:TrigCantBlock:DB$ MustBlock | ValidTgts$ Creature.DefenderCtrl | TgtPrompt$ Select target creature | SpellDescription$ Target creature blocks CARDNAME this turn if able. -SVar:Picture:http://www.wizards.com/global/images/magic/general/avalanche_tusker.jpg +T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigCantBlock | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, target creature defending player controls blocks it this combat if able. +SVar:TrigCantBlock:DB$ MustBlock | ValidTgts$ Creature.DefenderCtrl | TgtPrompt$ Select target creature Oracle:Whenever Avalanche Tusker attacks, target creature defending player controls blocks it this combat if able. diff --git a/forge-gui/res/cardsfolder/b/bloodrage_alpha.txt b/forge-gui/res/cardsfolder/b/bloodrage_alpha.txt index 8b5030532e9..dc135f02b2f 100644 --- a/forge-gui/res/cardsfolder/b/bloodrage_alpha.txt +++ b/forge-gui/res/cardsfolder/b/bloodrage_alpha.txt @@ -1,7 +1,7 @@ Name:Bloodrage Alpha ManaCost:3 R Types:Creature Wolf -PT:4/3 +PT:4/4 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerDescription$ When CARDNAME enters the battlefield, ABILITY SVar:TrigCharm:DB$ Charm | Choices$ DBTarget,DBDelayTrig SVar:DBTarget:DB$ Pump | ValidTgts$ Wolf.Other+YouCtrl,Werewolf.Other+YouCtrl | AILogic$ Fight | TgtPrompt$ Select another target Wolf or Werewolf you control | SubAbility$ DBFight | StackDescription$ {c:ThisTargetedCard} | SpellDescription$ Another target Wolf or Werewolf you control fights target creature you don't control. diff --git a/forge-gui/res/cardsfolder/c/captive_audience.txt b/forge-gui/res/cardsfolder/c/captive_audience.txt index a1aae500f63..cb9e37ed1df 100644 --- a/forge-gui/res/cardsfolder/c/captive_audience.txt +++ b/forge-gui/res/cardsfolder/c/captive_audience.txt @@ -5,11 +5,10 @@ R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ SVar:DBChooseOpp:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | ChoiceTitle$ Choose an opponent to give control to: | AILogic$ Curse | SubAbility$ MoveToPlay SVar:MoveToPlay:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Battlefield | Defined$ ReplacedCard | GainControl$ True | NewController$ ChosenPlayer T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigCharm | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, ABILITY -SVar:TrigCharm:DB$ Charm | Choices$ LifePact,DiscardPact,ZombiesPact | ChoiceRestriction$ ThisGame | CharmNum$ 1 +SVar:TrigCharm:DB$ Charm | Choices$ LifePact,DiscardPact,MakeZombies | ChoiceRestriction$ ThisGame | CharmNum$ 1 SVar:LifePact:DB$ SetLife | Defined$ You | LifeAmount$ 4 | SpellDescription$ Your life total becomes 4. SVar:DiscardPact:DB$ Discard | Defined$ You | Mode$ Hand | SpellDescription$ Discard your hand. -SVar:ZombiesPact:DB$ RepeatEach | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ MakeZombies | ChangeZoneTable$ True | SpellDescription$ Each opponent creates five 2/2 black Zombie creature tokens. -SVar:MakeZombies:DB$ Token | LegacyImage$ b 2 2 zombie rna | TokenAmount$ 5 | TokenScript$ b_2_2_zombie | TokenOwner$ Remembered | SpellDescription$ Each opponent creates five 2/2 black Zombie creature tokens. +SVar:MakeZombies:DB$ Token | TokenAmount$ 5 | TokenScript$ b_2_2_zombie | TokenOwner$ Opponent | SpellDescription$ Each opponent creates five 2/2 black Zombie creature tokens. SVar:SacMe:6 AI:RemoveDeck:Random DeckHas:Ability$Token diff --git a/forge-gui/res/cardsfolder/c/curse_of_bounty.txt b/forge-gui/res/cardsfolder/c/curse_of_bounty.txt index 9b2104aa9ee..84a46100c00 100644 --- a/forge-gui/res/cardsfolder/c/curse_of_bounty.txt +++ b/forge-gui/res/cardsfolder/c/curse_of_bounty.txt @@ -2,9 +2,8 @@ Name:Curse of Bounty ManaCost:1 G Types:Enchantment Aura Curse K:Enchant player -A:SP$ Attach | Cost$ 1 G | ValidTgts$ Player | AILogic$ Curse -T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigRepeat | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, untap all nonland permanents you control. Each opponent attacking that player untaps all nonland permanents they control. -SVar:TrigRepeat:DB$ RepeatEach | RepeatPlayers$ TriggeredAttackingPlayerAndYou | RepeatSubAbility$ TrigUntap -SVar:TrigUntap:DB$ UntapAll | Defined$ Player.IsRemembered | ValidCards$ Permanent.nonLand | SpellDescription$ Whenever enchanted player is attacked, untap all nonland permanents you control. Each opponent attacking that player untaps all nonland permanents they control. -SVar:Picture:http://www.wizards.com/global/images/magic/general/curse_of_vitality.jpg +A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse +T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigUntap | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, untap all nonland permanents you control. Each opponent attacking that player untaps all nonland permanents they control. +SVar:TrigUntap:DB$ UntapAll | Defined$ You | ValidCards$ Permanent.nonLand | SubAbility$ DBUntap +SVar:DBUntap:DB$ UntapAll | Defined$ TriggeredAttackingPlayer.Opponent | ValidCards$ Permanent.nonLand Oracle:Enchant player\nWhenever enchanted player is attacked, untap all nonland permanents you control. Each opponent attacking that player untaps all nonland permanents they control. diff --git a/forge-gui/res/cardsfolder/c/curse_of_disturbance.txt b/forge-gui/res/cardsfolder/c/curse_of_disturbance.txt index e0b164be4b6..993e35964ec 100644 --- a/forge-gui/res/cardsfolder/c/curse_of_disturbance.txt +++ b/forge-gui/res/cardsfolder/c/curse_of_disturbance.txt @@ -2,9 +2,8 @@ Name:Curse of Disturbance ManaCost:2 B Types:Enchantment Aura Curse K:Enchant player -A:SP$ Attach | Cost$ 2 B | ValidTgts$ Player | AILogic$ Curse -T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigRepeat | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, create a 2/2 black Zombie creature token. Each opponent attacking that player does the same. -SVar:TrigRepeat:DB$ RepeatEach | RepeatPlayers$ TriggeredAttackingPlayerAndYou | RepeatSubAbility$ TrigToken | ChangeZoneTable$ True -SVar:TrigToken:DB$ Token | TokenOwner$ Player.IsRemembered | TokenAmount$ 1 | TokenScript$ b_2_2_zombie | LegacyImage$ b 2 2 zombie c17 | SpellDescription$ Create a 2/2 black Zombie creature token. Activate only any time you could cast a sorcery. -SVar:Picture:http://www.wizards.com/global/images/magic/general/curse_of_vitality.jpg +A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse +T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, create a 2/2 black Zombie creature token. Each opponent attacking that player does the same. +SVar:TrigToken:DB$ Token | TokenScript$ b_2_2_zombie | SubAbility$ DBToken +SVar:DBToken:DB$ Token | TokenOwner$ TriggeredAttackingPlayer.Opponent | TokenScript$ b_2_2_zombie Oracle:Enchant player\nWhenever enchanted player is attacked, create a 2/2 black Zombie creature token. Each opponent attacking that player does the same. diff --git a/forge-gui/res/cardsfolder/c/curse_of_opulence.txt b/forge-gui/res/cardsfolder/c/curse_of_opulence.txt index 615942a8c45..14880a5cd66 100644 --- a/forge-gui/res/cardsfolder/c/curse_of_opulence.txt +++ b/forge-gui/res/cardsfolder/c/curse_of_opulence.txt @@ -2,8 +2,8 @@ Name:Curse of Opulence ManaCost:R Types:Enchantment Aura Curse 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$ c_a_gold_draw | TokenOwner$ Player.IsRemembered | TokenAmount$ 1 +A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse +T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigToken | 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:TrigToken:DB$ Token | TokenScript$ c_a_gold_draw | SubAbility$ DBToken +SVar:DBToken:DB$ Token | TokenOwner$ TriggeredAttackingPlayer.Opponent | TokenScript$ c_a_gold_draw 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/c/curse_of_verbosity.txt b/forge-gui/res/cardsfolder/c/curse_of_verbosity.txt index 2d7d225c3e2..801fd31431e 100644 --- a/forge-gui/res/cardsfolder/c/curse_of_verbosity.txt +++ b/forge-gui/res/cardsfolder/c/curse_of_verbosity.txt @@ -2,9 +2,8 @@ Name:Curse of Verbosity ManaCost:2 U Types:Enchantment Aura Curse K:Enchant player -A:SP$ Attach | Cost$ 2 U | ValidTgts$ Player | AILogic$ Curse -T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigRepeat | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, draw a card. Each opponent attacking that player does the same. -SVar:TrigRepeat:DB$ RepeatEach | RepeatPlayers$ TriggeredAttackingPlayerAndYou | RepeatSubAbility$ TrigDraw -SVar:TrigDraw:DB$ Draw | NumCards$ 1 | Defined$ Player.IsRemembered -SVar:Picture:http://www.wizards.com/global/images/magic/general/curse_of_verbosity.jpg +A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse +T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigDraw | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, draw a card. Each opponent attacking that player does the same. +SVar:TrigDraw:DB$ Draw | NumCards$ 1 | Defined$ You | SubAbility$ DBDraw +SVar:DBDraw:DB$ Draw | NumCards$ 1 | Defined$ TriggeredAttackingPlayer.Opponent Oracle:Enchant player\nWhenever enchanted player is attacked, you draw a card. Each opponent attacking that player does the same. diff --git a/forge-gui/res/cardsfolder/c/curse_of_vitality.txt b/forge-gui/res/cardsfolder/c/curse_of_vitality.txt index b8ca75058ab..8a5b73f6b5b 100644 --- a/forge-gui/res/cardsfolder/c/curse_of_vitality.txt +++ b/forge-gui/res/cardsfolder/c/curse_of_vitality.txt @@ -2,9 +2,9 @@ Name:Curse of Vitality ManaCost:2 W Types:Enchantment Aura Curse K:Enchant player -A:SP$ Attach | Cost$ 2 W | ValidTgts$ Player | AILogic$ Curse -T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigRepeat | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same. -SVar:TrigRepeat:DB$ RepeatEach | RepeatPlayers$ TriggeredAttackingPlayerAndYou | RepeatSubAbility$ TrigGainLife -SVar:TrigGainLife:DB$ GainLife | Defined$ Player.IsRemembered | LifeAmount$ 2 -SVar:Picture:http://www.wizards.com/global/images/magic/general/curse_of_vitality.jpg +A:SP$ Attach | ValidTgts$ Player | AILogic$ Curse +T:Mode$ AttackersDeclared | ValidCard$ Creature | AttackedTarget$ Player.EnchantedBy | Execute$ TrigGainLife | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same. +SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2 | SubAbility$ DBGainLife +SVar:DBGainLife:DB$ GainLife | Defined$ TriggeredAttackingPlayer.Opponent | LifeAmount$ 2 +DeckHas:Ability$LifeGain Oracle:Enchant player\nWhenever enchanted player is attacked, you gain 2 life. Each opponent attacking that player does the same. diff --git a/forge-gui/res/cardsfolder/d/daryl_hunter_of_walkers.txt b/forge-gui/res/cardsfolder/d/daryl_hunter_of_walkers.txt index e060d72c6af..607cd96adea 100644 --- a/forge-gui/res/cardsfolder/d/daryl_hunter_of_walkers.txt +++ b/forge-gui/res/cardsfolder/d/daryl_hunter_of_walkers.txt @@ -3,7 +3,7 @@ ManaCost:2 R G Types:Legendary Creature Human Archer PT:4/4 T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, target opponent creates three Walker tokens. -SVar:TrigToken:DB$ Token | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | TokenAmount$ 3 | TokenScript$ walker | TokenOwner$ TargetedPlayer +SVar:TrigToken:DB$ Token | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | TokenAmount$ 3 | TokenScript$ walker | TokenOwner$ TargetedPlayer | LockTokenScript$ True A:AB$ DealDamage | Cost$ T | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 2 | SpellDescription$ NICKNAME deals 2 damage to target creature. T:Mode$ ChangesZone | ValidCard$ Zombie.OppCtrl | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever a Zombie an opponent controls dies, draw a card. SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 diff --git a/forge-gui/res/cardsfolder/d/dementia_sliver.txt b/forge-gui/res/cardsfolder/d/dementia_sliver.txt index 6cf542fc81b..964d33e1481 100644 --- a/forge-gui/res/cardsfolder/d/dementia_sliver.txt +++ b/forge-gui/res/cardsfolder/d/dementia_sliver.txt @@ -4,8 +4,9 @@ Types:Creature Sliver PT:3/3 S:Mode$ Continuous | Affected$ Sliver | AddAbility$ ABDementiaNameCard | AddSVar$ DBDementiaReveal & DBDementiaDiscard | Description$ All Slivers have "{T}: Choose a card name. Target opponent reveals a card at random from their hand. If that card has the chosen name, that player discards it. Activate only during your turn." SVar:ABDementiaNameCard:AB$ NameCard | Cost$ T | Defined$ You | SubAbility$ DBDementiaReveal | SpellDescription$ Choose a card name. Target opponent reveals a card at random from their hand. If that card has the chosen name, that player discards it. Activate only during your turn. -SVar:DBDementiaReveal:DB$ Reveal | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | Random$ True | PlayerTurn$ True | SubAbility$ DBDementiaDiscard -SVar:DBDementiaDiscard:DB$ Discard | DiscardValid$ Card.NamedCard | Mode$ TgtChoose | Defined$ Targeted +SVar:DBDementiaReveal:DB$ Reveal | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | Random$ True | PlayerTurn$ True | RememberRevealed$ True | SubAbility$ DBDementiaDiscard +SVar:DBDementiaDiscard:DB$ Discard | DiscardValid$ Card.NamedCard+IsRemembered | Mode$ TgtChoose | Defined$ Targeted | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True AI:RemoveDeck:All AI:RemoveDeck:Random SVar:Picture:http://www.wizards.com/global/images/magic/general/dementia_sliver.jpg diff --git a/forge-gui/res/cardsfolder/e/elephant_resurgence.txt b/forge-gui/res/cardsfolder/e/elephant_resurgence.txt index 543b4946a5d..000305a7031 100644 --- a/forge-gui/res/cardsfolder/e/elephant_resurgence.txt +++ b/forge-gui/res/cardsfolder/e/elephant_resurgence.txt @@ -1,12 +1,10 @@ Name:Elephant Resurgence ManaCost:1 G Types:Sorcery -A:SP$ RepeatEach | Cost$ 1 G | RepeatPlayers$ Player | RepeatSubAbility$ DBToken | ChangeZoneTable$ True | SpellDescription$ Each player creates a green Elephant creature token. Those creatures have "This creature's power and toughness are each equal to the number of creature cards in its controller's graveyard." -SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_x_x_elephant_resurgence | TokenOwner$ Player.IsRemembered | LegacyImage$ g x x elephant resurgence pcy +A:SP$ Token | TokenScript$ g_x_x_elephant_resurgence | TokenOwner$ Player | SpellDescription$ Each player creates a green Elephant creature token. Those creatures have "This creature's power and toughness are each equal to the number of creature cards in its controller's graveyard." SVar:NeedsToPlayVar:Z GE2 SVar:Z:SVar$Z1/Minus.Z2 SVar:Z1:Count$ValidGraveyard Creature.YouOwn SVar:Z2:Count$ValidGraveyard Creature.OppOwn AI:RemoveDeck:Random -SVar:Picture:http://www.wizards.com/global/images/magic/general/elephant_resurgence.jpg Oracle:Each player creates a green Elephant creature token. Those creatures have "This creature's power and toughness are each equal to the number of creature cards in its controller's graveyard." diff --git a/forge-gui/res/cardsfolder/e/ethereal_investigator.txt b/forge-gui/res/cardsfolder/e/ethereal_investigator.txt index 49245c97345..51535d12e94 100644 --- a/forge-gui/res/cardsfolder/e/ethereal_investigator.txt +++ b/forge-gui/res/cardsfolder/e/ethereal_investigator.txt @@ -6,7 +6,7 @@ K:Flying T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigInvestigate | TriggerDescription$ When CARDNAME enters the battlefield, investigate X times, where X is the number of opponents you have. (To investigate, create a colorless Clue artifact token with "{2}, Sacrifice this artifact: Draw a card.") SVar:TrigInvestigate:DB$ Investigate | Num$ X SVar:X:PlayerCountOpponents$Amount -T:Mode$ Drawn | ValidCard$ Card.YouCtrl | Number$ 2 | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever you draw your second card each turn, put a +1/+1 counter on CARDNAME. +T:Mode$ Drawn | ValidCard$ Card.YouCtrl | Number$ 2 | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever you draw your second card each turn, create a 1/1 white Spirit creature token with flying. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_spirit_flying DeckHas:Ability$Token & Ability$Sacrifice Oracle:Flying\nWhen Ethereal Investigator enters the battlefield, investigate X times, where X is the number of opponents you have. (To investigate, create a colorless Clue artifact token with "{2}, Sacrifice this artifact: Draw a card.")\nWhenever you draw your second card each turn, create a 1/1 white Spirit creature token with flying. diff --git a/forge-gui/res/cardsfolder/f/fearsome_whelp.txt b/forge-gui/res/cardsfolder/f/fearsome_whelp.txt index 28c35e72d31..4da42ba4aec 100644 --- a/forge-gui/res/cardsfolder/f/fearsome_whelp.txt +++ b/forge-gui/res/cardsfolder/f/fearsome_whelp.txt @@ -3,11 +3,12 @@ ManaCost:1 R Types:Creature Dragon PT:1/1 K:Flying -T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ At the beginning of your end step, each Dragon card in your hand perpetually gains "This spell costs {1} less to cast." +K:Haste +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ At the beginning of your upkeep, each Dragon card in your hand perpetually gains "This spell costs {1} less to cast." SVar:TrigEffect:DB$ Effect | RememberObjects$ ValidHand Dragon.YouOwn | StaticAbilities$ PerpetualAbility | Duration$ Permanent | Triggers$ Update | Name$ Fearsome Whelp's Perpetual Effect SVar:PerpetualAbility:Mode$ Continuous | Affected$ Card.IsRemembered | AddStaticAbility$ DragonReduceCost | EffectZone$ Command | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | Description$ Each Dragon card in your hand perpetually gains "This spell costs {1} less to cast." SVar:DragonReduceCost:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ 1 | EffectZone$ All | Description$ This spell costs {1} less to cast. SVar:Update:Mode$ ChangesZone | Origin$ Any | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBUpdate SVar:DBUpdate:DB$ UpdateRemember DeckHints:Type$Dragon -Oracle:Flying\nAt the beginning of your end step, each Dragon card in your hand perpetually gains "This spell costs {1} less to cast. +Oracle:Flying, haste\nAt the beginning of your upkeep, each Dragon card in your hand perpetually gains "This spell costs {1} less to cast." diff --git a/forge-gui/res/cardsfolder/f/fumiko_the_lowblood.txt b/forge-gui/res/cardsfolder/f/fumiko_the_lowblood.txt index e136817f37a..081689561f1 100644 --- a/forge-gui/res/cardsfolder/f/fumiko_the_lowblood.txt +++ b/forge-gui/res/cardsfolder/f/fumiko_the_lowblood.txt @@ -2,7 +2,7 @@ Name:Fumiko the Lowblood ManaCost:2 R R Types:Legendary Creature Human Samurai PT:3/2 -K:Bushido:X +S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Bushido:N | CalcKeywordN$ N | Description$ Fumiko the Lowblood has bushido X, where X is the number of attacking creatures. +SVar:N:Count$Valid Creature.attacking S:Mode$ Continuous | Affected$ Creature.OppCtrl | AddHiddenKeyword$ CARDNAME attacks each combat if able. | Description$ Creatures your opponents control attack each combat if able. -SVar:Picture:http://www.wizards.com/global/images/magic/general/fumiko_the_lowblood.jpg Oracle:Fumiko the Lowblood has bushido X, where X is the number of attacking creatures. (Whenever this creature blocks or becomes blocked, it gets +X/+X until end of turn.)\nCreatures your opponents control attack each combat if able. diff --git a/forge-gui/res/cardsfolder/g/ghitu_lavarunner.txt b/forge-gui/res/cardsfolder/g/ghitu_lavarunner.txt index 872f960be51..7fc30769530 100644 --- a/forge-gui/res/cardsfolder/g/ghitu_lavarunner.txt +++ b/forge-gui/res/cardsfolder/g/ghitu_lavarunner.txt @@ -5,5 +5,6 @@ PT:1/2 S:Mode$ Continuous | Affected$ Card.Self | CheckSVar$ X | SVarCompare$ GE2 | AddPower$ 1 | AddKeyword$ Haste | Description$ As long as there are two or more instant and/or sorcery cards in your graveyard, CARDNAME gets +1/+0 and has haste. SVar:X:Count$ValidGraveyard Instant.YouOwn,Sorcery.YouOwn SVar:BuffedBy:Instant,Sorcery +SVar:PlayMain1:TRUE DeckHints:Type$Instant|Sorcery Oracle:As long as there are two or more instant and/or sorcery cards in your graveyard, Ghitu Lavarunner gets +1/+0 and has haste. diff --git a/forge-gui/res/cardsfolder/g/gravecrawler.txt b/forge-gui/res/cardsfolder/g/gravecrawler.txt index 19eceefe8aa..f68b694c1ed 100644 --- a/forge-gui/res/cardsfolder/g/gravecrawler.txt +++ b/forge-gui/res/cardsfolder/g/gravecrawler.txt @@ -3,7 +3,7 @@ ManaCost:B Types:Creature Zombie PT:2/1 K:CARDNAME can't block. -S:Mode$ Continuous | Affected$ Card.Self | AffectedZone$ GraveYard | EffectZone$ Graveyard | MayPlay$ True | IsPresent$ Zombie.YouCtrl | Description$ You may cast CARDNAME from your graveyard as long as you control a Zombie. +S:Mode$ Continuous | Affected$ Card.Self | AffectedZone$ Graveyard | EffectZone$ Graveyard | MayPlay$ True | IsPresent$ Zombie.YouCtrl | Description$ You may cast CARDNAME from your graveyard as long as you control a Zombie. SVar:SacMe:3 SVar:DiscardMe:3 DeckHints:Type$Zombie diff --git a/forge-gui/res/cardsfolder/i/impetuous_devils.txt b/forge-gui/res/cardsfolder/i/impetuous_devils.txt index e55525ccaff..e0f8673e432 100644 --- a/forge-gui/res/cardsfolder/i/impetuous_devils.txt +++ b/forge-gui/res/cardsfolder/i/impetuous_devils.txt @@ -5,10 +5,9 @@ PT:6/1 K:Haste K:Trample T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigProvoke | TriggerDescription$ When CARDNAME attacks, up to one target creature defending player controls blocks it this combat if able. -SVar:TrigProvoke:DB$ MustBlock | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature.DefenderCtrl | Duration$ UntilEndOfCombat | TgtPrompt$ Select up to one target creature defending player controls +SVar:TrigProvoke:DB$ MustBlock | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature.DefenderCtrl | TgtPrompt$ Select up to one target creature defending player controls T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | Execute$ TrigSac | TriggerDescription$ At the beginning of the end step, sacrifice CARDNAME. SVar:TrigSac:DB$ Sacrifice | SacValid$ Self SVar:EndOfTurnLeavePlay:True SVar:PlayMain1:TRUE -SVar:Picture:http://www.wizards.com/global/images/magic/general/impetuous_devils.jpg Oracle:Trample, haste\nWhen Impetuous Devils attacks, up to one target creature defending player controls blocks it this combat if able.\nAt the beginning of the end step, sacrifice Impetuous Devils. diff --git a/forge-gui/res/cardsfolder/i/inquisitor_captain.txt b/forge-gui/res/cardsfolder/i/inquisitor_captain.txt index fc68b6636b9..0c4e1bcc5be 100644 --- a/forge-gui/res/cardsfolder/i/inquisitor_captain.txt +++ b/forge-gui/res/cardsfolder/i/inquisitor_captain.txt @@ -3,7 +3,7 @@ ManaCost:3 W Types:Creature Human Cleric PT:3/3 K:Vigilance -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | CheckSVar$ Z | SVarCompare$ GE20 | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, if there are twenty or more creature cards with mana value 3 or less among cards in your graveyard, hand, and library, seek two creature cards with mana value 3 or less. Put one of them onto the battlefield and shuffle the other into your library. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.wasCast+Self | CheckSVar$ Z | SVarCompare$ GE20 | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it and there are twenty or more creature cards with mana value 3 or less among cards in your graveyard, hand, and library, seek two creature cards with mana value 3 or less. Put one of them onto the battlefield and shuffle the other into your library. SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Library | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Creature.YouOwn+cmcLE3 | ChangeNum$ 2 | RememberChanged$ True | SubAbility$ DBChangeZone1 SVar:DBChangeZone1:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Creature.IsRemembered | ChangeNum$ 1 | Mandatory$ True | NoLooking$ True | SelectPrompt$ Select a card for the battlefield | Shuffle$ True | SubAbility$ DBChangeZone2 | StackDescription$ None SVar:DBChangeZone2:DB$ ChangeZone | Origin$ Library | Destination$ Library | ChangeType$ Creature.IsRemembered | Mandatory$ True | NoLooking$ True | StackDescription$ None | SubAbility$ DBCleanup @@ -12,4 +12,4 @@ SVar:X:Count$ValidGraveyard Creature.YouOwn+cmcLE3 SVar:Y:Count$ValidLibrary Creature.YouOwn+cmcLE3/Plus.X SVar:Z:Count$ValidHand Creature.YouOwn+cmcLE3/Plus.Y DeckNeeds:Type$Creature -Oracle:Vigilance\nWhen Inquisitor Captain enters the battlefield, if there are twenty or more creature cards with mana value 3 or less among cards in your graveyard, hand, and library, seek two creature cards with mana value 3 or less. Put one of them onto the battlefield and shuffle the other into your library. +Oracle:Vigilance\nWhen Inquisitor Captain enters the battlefield, if you cast it and there are twenty or more creature cards with mana value 3 or less among cards in your graveyard, hand, and library, seek two creature cards with mana value 3 or less. Put one of them onto the battlefield and shuffle the other into your library. diff --git a/forge-gui/res/cardsfolder/k/kodama_of_the_center_tree.txt b/forge-gui/res/cardsfolder/k/kodama_of_the_center_tree.txt index b424a0fd17f..0dc4fc35848 100644 --- a/forge-gui/res/cardsfolder/k/kodama_of_the_center_tree.txt +++ b/forge-gui/res/cardsfolder/k/kodama_of_the_center_tree.txt @@ -2,12 +2,11 @@ Name:Kodama of the Center Tree ManaCost:4 G Types:Legendary Creature Spirit PT:*/* -K:Soulshift:X:, where X is the number of Spirits you control.:Spirit.YouCtrl S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ CARDNAME's power and toughness are each equal to the number of Spirits you control. +S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Soulshift:N | CalcKeywordN$ X | Description$ CARDNAME has soulshift X, where X is the number of Spirits you control. SVar:X:Count$Valid Spirit.YouCtrl AI:RemoveDeck:Random SVar:BuffedBy:Spirit SVar:NoZeroToughnessAI:True DeckHints:Type$Spirit -SVar:Picture:http://www.wizards.com/global/images/magic/general/kodama_of_the_center_tree.jpg Oracle:Kodama of the Center Tree's power and toughness are each equal to the number of Spirits you control.\nKodama of the Center Tree has soulshift X, where X is the number of Spirits you control. (When this creature dies, you may return target Spirit card with mana value X or less from your graveyard to your hand.) diff --git a/forge-gui/res/cardsfolder/l/lucille.txt b/forge-gui/res/cardsfolder/l/lucille.txt index 4758e20325c..56d88fa3851 100644 --- a/forge-gui/res/cardsfolder/l/lucille.txt +++ b/forge-gui/res/cardsfolder/l/lucille.txt @@ -4,7 +4,7 @@ Types:Legendary Artifact Equipment S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 2 | AddKeyword$ Menace | Description$ Equipped creature gets +2/+0 and has menace. T:Mode$ Attacks | ValidCard$ Card.EquippedBy | Execute$ TrigSac | TriggerDescription$ Whenever equipped creature attacks, defending player sacrifices a creature. If they do, you create a Walker token. SVar:TrigSac:DB$ Sacrifice | Defined$ TriggeredDefendingPlayer | SacValid$ Creature | Amount$ 1 | RememberSacrificed$ True | SubAbility$ DBToken -SVar:DBToken:DB$ Token | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | TokenAmount$ 1 | TokenScript$ walker | TokenOwner$ You | SubAbility$ DBCleanup +SVar:DBToken:DB$ Token | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | TokenAmount$ 1 | TokenScript$ walker | TokenOwner$ You | LockTokenScript$ True | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True K:Equip:4 Oracle:Equipped creature gets +2/+0 and has menace.\nWhenever equipped creature attacks, defending player sacrifices a creature. If they do, you create a Walker token.\nEquip {4} diff --git a/forge-gui/res/cardsfolder/m/marang_river_prowler.txt b/forge-gui/res/cardsfolder/m/marang_river_prowler.txt index 95d5d5a6a92..f52ba3945ce 100644 --- a/forge-gui/res/cardsfolder/m/marang_river_prowler.txt +++ b/forge-gui/res/cardsfolder/m/marang_river_prowler.txt @@ -4,9 +4,8 @@ Types:Creature Human Rogue PT:2/1 K:Unblockable K:CARDNAME can't block. -S:Mode$ Continuous | Affected$ Card.Self | EffectZone$ Graveyard | MayPlay$ True | IsPresent$ Permanent.Black+YouCtrl,Permanent.Green+YouCtrl | Description$ You may cast CARDNAME from you graveyard as long as you control a black or green permanent. +S:Mode$ Continuous | Affected$ Card.Self | AffectedZone$ Graveyard | EffectZone$ Graveyard | MayPlay$ True | IsPresent$ Permanent.Black+YouCtrl,Permanent.Green+YouCtrl | Description$ You may cast CARDNAME from you graveyard as long as you control a black or green permanent. SVar:SacMe:3 SVar:DiscardMe:3 DeckHints:Color$Black|Green -SVar:Picture:http://www.wizards.com/global/images/magic/general/marang_river_prowler.jpg Oracle:Marang River Prowler can't block and can't be blocked.\nYou may cast Marang River Prowler from your graveyard as long as you control a black or green permanent. diff --git a/forge-gui/res/cardsfolder/m/michonne_ruthless_survivor.txt b/forge-gui/res/cardsfolder/m/michonne_ruthless_survivor.txt index fb0d6e18b6b..4f6411abc93 100644 --- a/forge-gui/res/cardsfolder/m/michonne_ruthless_survivor.txt +++ b/forge-gui/res/cardsfolder/m/michonne_ruthless_survivor.txt @@ -4,9 +4,8 @@ ManaCost:3 B G Types:Legendary Creature Human Warrior PT:3/3 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When NICKNAME enters the battlefield, create two Walker tokens. -SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ walker | TokenOwner$ You -S:Mode$ Continuous | Affected$ Card.Self | CheckSVar$ Equipped | SVarCompare$ EQ1 | AddHiddenKeyword$ CARDNAME must be blocked if able. | Description$ As long as NICKNAME is equipped, she must be blocked if able. -SVar:Equipped:Count$Valid Card.Self+equipped +SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ walker | TokenOwner$ You | LockTokenScript$ True +S:Mode$ Continuous | Affected$ Card.Self+equipped | AddHiddenKeyword$ CARDNAME must be blocked if able. | Description$ As long as NICKNAME is equipped, she must be blocked if able. SVar:EquipMe:Once T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | CheckSVar$ Zombies | NoResolvingCheck$ True | SVarCompare$ GE2 | Execute$ TrigPump | TriggerDescription$ Whenever NICKNAME and at least two Zombies attack, she gains indestructible until end of turn. SVar:TrigPump:DB$ Pump | Defined$ Self | KW$ Indestructible diff --git a/forge-gui/res/cardsfolder/p/prowling_geistcatcher.txt b/forge-gui/res/cardsfolder/p/prowling_geistcatcher.txt index 8d00f37f49e..d816bf99c71 100644 --- a/forge-gui/res/cardsfolder/p/prowling_geistcatcher.txt +++ b/forge-gui/res/cardsfolder/p/prowling_geistcatcher.txt @@ -6,7 +6,7 @@ T:Mode$ Sacrificed | ValidPlayer$ You | ValidCard$ Creature.Other | TriggerZones SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Exile | SubAbility$ TokenPlus SVar:TokenPlus:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ConditionDefined$ TriggeredCardLKICopy | ConditionPresent$ Creature.token T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME leaves the battlefield, return each card exiled with it to the battlefield under your control. -SVar:TrigReturn:DB$ ChangeZoneAll | ChangeTypes$ Card.ExiledWithSource | Origin$ Exile | Destination$ Battlefield | GainControl$ True +SVar:TrigReturn:DB$ ChangeZoneAll | ChangeType$ Card.ExiledWithSource | Origin$ Exile | Destination$ Battlefield | GainControl$ True DeckNeeds:Ability$Sacrifice DeckHas:Ability$Counters DeckHints:Ability$Token diff --git a/forge-gui/res/cardsfolder/p/puppet_raiser.txt b/forge-gui/res/cardsfolder/p/puppet_raiser.txt index c551ac819b8..8d616af25ab 100644 --- a/forge-gui/res/cardsfolder/p/puppet_raiser.txt +++ b/forge-gui/res/cardsfolder/p/puppet_raiser.txt @@ -1,7 +1,7 @@ Name:Puppet Raiser ManaCost:3 B Types:Creature Zombie Wizard -PT:3/3 +PT:3/4 T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | IsPresent$ Card.Creature+YouOwn | PresentZone$ Graveyard | PresentCompare$ GE1 | Execute$ TrigExile | TriggerDescription$ At the beginning of your end step, exile up to one target creature card from your graveyard. If you do, seek a creature card with mana value equal to the mana value of that card plus one. That card perpetually gains menace. SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select up to one target creature card in your graveyard | TargetMin$ 0 | TargetMax$ 1 | RememberChanged$ True | SubAbility$ DBSeek SVar:DBSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Creature.cmcEQX | ChangeNum$ 1 | Imprint$ True | SubAbility$ DBEffect diff --git a/forge-gui/res/cardsfolder/rebalanced/a-acererak_the_archlich.txt b/forge-gui/res/cardsfolder/rebalanced/a-acererak_the_archlich.txt new file mode 100644 index 00000000000..94834d53c89 --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-acererak_the_archlich.txt @@ -0,0 +1,14 @@ +Name:A-Acererak the Archlich +ManaCost:2 B +Types:Legendary Creature Zombie Wizard +PT:5/5 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | CheckSVar$ X | SVarCompare$ LT1 | Execute$ TrigBounce | TriggerDescription$ When CARDNAME enters the battlefield, if you haven't completed Tomb of Annihilation, return CARDNAME to its owner's hand and venture into the dungeon. +SVar:TrigBounce:DB$ ChangeZone | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBVenture +SVar:DBVenture:DB$ Venture +SVar:X:PlayerCountPropertyYou$DungeonCompletedNamed_Tomb of Annihilation +T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME attacks, create a number of 2/2 black Zombie creature tokens equal to the number of opponents you have. +SVar:TrigToken:DB$ Token | TokenAmount$ X | TokenScript$ b_2_2_zombie | TokenOwner$ You +SVar:X:PlayerCountOpponents$Amount +DeckHas:Ability$Token +DeckHints:Type$Zombie +Oracle:When Acererak the Archlich enters the battlefield, if you haven't completed Tomb of Annihilation, return Acererak the Archlich to its owner's hand and venture into the dungeon.\nWhenever Acererak the Archlich attacks, create a number of 2/2 black Zombie creature tokens equal to the number of opponents you have. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-cloister_gargoyle.txt b/forge-gui/res/cardsfolder/rebalanced/a-cloister_gargoyle.txt new file mode 100644 index 00000000000..7c82b3c4c1e --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-cloister_gargoyle.txt @@ -0,0 +1,9 @@ +Name:A-Cloister Gargoyle +ManaCost:1 W +Types:Artifact Creature Gargoyle +PT:0/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ DBVenture | TriggerDescription$ When CARDNAME enters the battlefield, venture into the dungeon. +SVar:DBVenture:DB$ Venture | Defined$ You +S:Mode$ Continuous | Affected$ Card.Self | AddPower$ 3 | AddKeyword$ Flying | CheckSVar$ X | SVarCompare$ GE1 | Description$ As long as you've completed a dungeon, CARDNAME gets +3/+0 and has flying. +SVar:X:PlayerCountPropertyYou$DungeonsCompleted +Oracle:When Cloister Gargoyle enters the battlefield, venture into the dungeon.\nAs long as you've completed a dungeon, Cloister Gargoyle gets +3/+0 and has flying. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-divide_by_zero.txt b/forge-gui/res/cardsfolder/rebalanced/a-divide_by_zero.txt new file mode 100644 index 00000000000..a827ebcb590 --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-divide_by_zero.txt @@ -0,0 +1,6 @@ +Name:A-Divide by Zero +ManaCost:2 U +Types:Instant +A:SP$ ChangeZone | ValidTgts$ Permanent.cmcGE1,Card.inZoneStack+cmcGE1 | TgtZone$ Stack,Battlefield | Origin$ Battlefield,Stack | Fizzle$ True | Destination$ Hand | SubAbility$ DBLearn | SpellDescription$ Return target spell or permanent with mana value 1 or greater to its owner's hand. If its mana value was 4 or less, learn. +SVar:DBLearn:DB$ Learn | ConditionDefined$ Targeted | ConditionPresent$ Card.cmcLE4 | ConditionCompare$ EQ1 +Oracle:Return target spell or permanent with mana value 1 or greater to its owner's hand. If its mana value was 4 or less, learn. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-dungeon_descent.txt b/forge-gui/res/cardsfolder/rebalanced/a-dungeon_descent.txt new file mode 100644 index 00000000000..59bd35b0f9f --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-dungeon_descent.txt @@ -0,0 +1,6 @@ +Name:A-Dungeon Descent +ManaCost:no cost +Types:Land +A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. +A:AB$ Venture | Cost$ 1 T tapXType<1/Creature.Legendary/legendary creature> | SorcerySpeed$ True | SpellDescription$ Venture into the dungeon. Activate only as a sorcery. +Oracle:{T}: Add {C}.\n{1}, {T}, Tap an untapped legendary creature you control: Venture into the dungeon. Activate only as a sorcery. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-ellywick_tumblestrum.txt b/forge-gui/res/cardsfolder/rebalanced/a-ellywick_tumblestrum.txt new file mode 100644 index 00000000000..10976362388 --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-ellywick_tumblestrum.txt @@ -0,0 +1,13 @@ +Name:A-Ellywick Tumblestrum +ManaCost:2 G G +Types:Legendary Planeswalker Ellywick +Loyalty:4 +A:AB$ Venture | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | Defined$ You | SpellDescription$ Venture into the dungeon. +A:AB$ Dig | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | DigNum$ 6 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Creature | ForceRevealToController$ True | RememberChanged$ True | RestRandomOrder$ True | SubAbility$ DBGainLife | SpellDescription$ Look at the top six cards of your library. You may reveal a creature card from among them and put it into your hand. If it's legendary, you gain 3 life. Put the rest on the bottom of your library in a random order. +SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 3 | ConditionCheckSVar$ IsLegendary | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup +SVar:IsLegendary:Count$ValidHand Creature.Legendary+IsRemembered +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +A:AB$ Effect | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | Name$ Emblem - Ellywick Tumblestrum | Image$ emblem_ellywick_tumblestrum | StaticAbilities$ STOverrun | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Creatures you control have trample and haste and get +2/+2 for each differently named dungeon you've completed." +SVar:STOverrun:Mode$ Continuous | EffectZone$ Command | Affected$ Creature.YouCtrl | AffectedZone$ Battlefield | AddPower$ X | AddToughness$ X | AddKeyword$ Trample & Haste | Description$ Creatures you control have trample and haste and get +2/+2 for each differently named dungeon you've completed. +SVar:X:PlayerCountPropertyYou$DifferentlyNamedDungeonsCompleted/Twice +Oracle:[+1]: Venture into the dungeon.\n[−2]: Look at the top six cards of your library. You may reveal a creature card from among them and put it into your hand. If it's legendary, you gain 3 life. Put the rest on the bottom of your library in a random order.\n[−6]: You get an emblem with "Creatures you control have trample and haste and get +2/+2 for each differently named dungeon you've completed." diff --git a/forge-gui/res/cardsfolder/rebalanced/a-fates_reversal.txt b/forge-gui/res/cardsfolder/rebalanced/a-fates_reversal.txt new file mode 100644 index 00000000000..17bf5a9e032 --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-fates_reversal.txt @@ -0,0 +1,7 @@ +Name:A-Fates' Reversal +ManaCost:B +Types:Sorcery +A:SP$ ChangeZone | Cost$ 1 B | Origin$ Graveyard | Destination$ Hand | TgtPrompt$ Select target creature card in your graveyard | ValidTgts$ Creature.YouOwn | TargetMin$ 0 | TargetMax$ 1 | SubAbility$ DBVenture | SpellDescription$ Return up to one target creature card from your graveyard to your hand. Venture into the dungeon. +SVar:DBVenture:DB$ Venture +DeckHints:Ability$Graveyard +Oracle:Return up to one target creature card from your graveyard to your hand. Venture into the dungeon. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-find_the_path.txt b/forge-gui/res/cardsfolder/rebalanced/a-find_the_path.txt new file mode 100644 index 00000000000..efb5db7d433 --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-find_the_path.txt @@ -0,0 +1,10 @@ +Name:A-Find the Path +ManaCost:2 G +Types:Enchantment Aura +K:Enchant land +A:SP$ Attach | Cost$ 2 G | ValidTgts$ Land | AILogic$ Pump +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ DBVenture | TriggerDescription$ When CARDNAME enters the battlefield, venture into the dungeon. +SVar:DBVenture:DB$ Venture | Defined$ You +S:Mode$ Continuous | Affected$ Land.EnchantedBy | AddAbility$ ABMana | Description$ Enchanted land has "{T}: Add two mana of any one colour." +SVar:ABMana:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 2 | SpellDescription$ Add two mana of any one colour. +Oracle:Enchant land\nWhen Find the Path enters the battlefield, venture into the dungeon.\nEnchanted land has "{T}: Add two mana of any one colour." diff --git a/forge-gui/res/cardsfolder/rebalanced/a-hullbreaker_horror.txt b/forge-gui/res/cardsfolder/rebalanced/a-hullbreaker_horror.txt new file mode 100644 index 00000000000..422b5ce2184 --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-hullbreaker_horror.txt @@ -0,0 +1,10 @@ +Name:A-Hullbreaker Horror +ManaCost:5 U U +Types:Creature Kraken Horror +PT:7/8 +K:Flash +T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ You | Execute$ TrigCharm | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast a spell, ABILITY +SVar:TrigCharm:DB$ Charm | Choices$ ControlReturn,ControlBounce | MinCharmNum$ 0 | CharmNum$ 1 +SVar:ControlReturn:DB$ ChangeZone | ValidTgts$ Card.YouDontCtrl | TgtPrompt$ Select target spell you don't control | TgtZone$ Stack | Origin$ Stack | Fizzle$ True | Destination$ Hand | SpellDescription$ Return target spell you don't control to its owner's hand. +SVar:ControlBounce:DB$ ChangeZone | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | TgtZone$ Battlefield | Origin$ Battlefield | Destination$ Hand | SpellDescription$ Return target nonland permanent to its owner's hand. +Oracle:Flash\nWhenever you cast a spell, choose up to one —\n• Return target spell you don't control to its owner's hand.\n• Return target nonland permanent to its owner's hand. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-lier_disciple_of_the_drowned.txt b/forge-gui/res/cardsfolder/rebalanced/a-lier_disciple_of_the_drowned.txt new file mode 100644 index 00000000000..530082fa8ae --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-lier_disciple_of_the_drowned.txt @@ -0,0 +1,9 @@ +Name:A-Lier, Disciple of the Drowned +ManaCost:3 U U +Types:Legendary Creature Human Wizard +PT:3/4 +S:Mode$ Continuous | Affected$ Card | AddHiddenKeyword$ This spell can't be countered. | AffectedZone$ Stack | Description$ Spells can't be countered. +S:Mode$ Continuous | Affected$ Instant.YouOwn,Sorcery.YouOwn | AffectedZone$ Graveyard | AddKeyword$ Flashback | Condition$ PlayerTurn | Description$ As long as it's your turn, each instant and sorcery card in your graveyard has flashback. The flashback cost is equal to that card's mana cost. +DeckHints:Type$Instant|Sorcery +DeckHas:Ability$Graveyard +Oracle:Spells can't be countered.\nAs long as it's your turn, each instant and sorcery card in your graveyard has flashback. The flashback cost is equal to that card's mana cost. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-precipitous_drop.txt b/forge-gui/res/cardsfolder/rebalanced/a-precipitous_drop.txt new file mode 100644 index 00000000000..cccb66690df --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-precipitous_drop.txt @@ -0,0 +1,11 @@ +Name:A-Precipitous Drop +ManaCost:1 B +Types:Enchantment Aura +K:Enchant creature +A:SP$ Attach | Cost$ 2 B | ValidTgts$ Creature | AILogic$ Curse +T:Mode$ ChangesZone | ValidCard$ Card.Self | Destination$ Battlefield | Execute$ TrigVenture | TriggerDescription$ When CARDNAME enters the battlefield, venture into the dungeon. +SVar:TrigVenture:DB$ Venture +S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ -X | AddToughness$ -X | Description$ Enchanted creature gets -2/-2. It gets -5/-5 instead as long as you've completed a dungeon. +SVar:X:Count$Compare Y GE1.5.2 +SVar:Y:PlayerCountPropertyYou$DungeonsCompleted +Oracle:Enchant creature\nWhen Precipitous Drop enters the battlefield, venture into the dungeon.\nEnchanted creature gets -2/-2. It gets -5/-5 instead as long as you've completed a dungeon. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-teferi_time_raveler.txt b/forge-gui/res/cardsfolder/rebalanced/a-teferi_time_raveler.txt new file mode 100644 index 00000000000..7b266bd48e0 --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-teferi_time_raveler.txt @@ -0,0 +1,11 @@ +Name:A-Teferi, Time Raveler +ManaCost:2 W U +Types:Legendary Planeswalker Teferi +Loyalty:5 +S:Mode$ CantBeCast | ValidCard$ Card | Condition$ PlayerTurn | Caster$ Opponent | Description$ Your opponents can't cast spells during your turn. +A:AB$ Effect | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | StaticAbilities$ STPlay | Duration$ UntilYourNextTurn | AILogic$ Main2 | SpellDescription$ Until your next turn, you may cast sorcery spells as though they had flash. +SVar:STPlay:Mode$ CastWithFlash | ValidCard$ Sorcery | ValidSA$ Spell | EffectZone$ Command | Caster$ You | Description$ Until your next turn, you may cast sorcery spells as though they had flash. +SVar:PlayMain1:TRUE +A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | Origin$ Battlefield | Destination$ Hand | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Artifact,Creature,Enchantment | TgtPrompt$ Select target artifact, creature, or enchantment | SpellDescription$ Return up to one target artifact, creature, or enchantment to its owner's hand. Draw a card. | SubAbility$ DBDraw +SVar:DBDraw:DB$ Draw | NumCards$ 1 +Oracle:Your opponents can't cast spells during your turn.\n[+1]: Until your next turn, you may cast sorcery spells as though they had flash.\n[−3]: Return up to one target artifact, creature, or enchantment to its owner's hand. Draw a card. diff --git a/forge-gui/res/cardsfolder/rebalanced/a-triumphant_adventurer.txt b/forge-gui/res/cardsfolder/rebalanced/a-triumphant_adventurer.txt new file mode 100644 index 00000000000..28a957e9129 --- /dev/null +++ b/forge-gui/res/cardsfolder/rebalanced/a-triumphant_adventurer.txt @@ -0,0 +1,10 @@ +Name:A-Triumphant Adventurer +ManaCost:W B +Types:Creature Human Knight +PT:2/1 +K:Deathtouch +S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ First Strike | Condition$ PlayerTurn | Description$ As long as it's your turn, CARDNAME has first strike. +T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ DBVenture | Secondary$ True | TriggerDescription$ Whenever CARDNAME attacks, venture into the dungeon. +SVar:DBVenture:DB$ Venture | Defined$ You +SVar:HasAttackEffect:TRUE +Oracle:Deathtouch\nAs long as it's your turn, Triumphant Adventurer has first strike.\nWhenever Triumphant Adventurer attacks, venture into the dungeon. diff --git a/forge-gui/res/cardsfolder/s/sanguine_brushstroke.txt b/forge-gui/res/cardsfolder/s/sanguine_brushstroke.txt index 49d6696e7f8..a9e2620d2b6 100644 --- a/forge-gui/res/cardsfolder/s/sanguine_brushstroke.txt +++ b/forge-gui/res/cardsfolder/s/sanguine_brushstroke.txt @@ -4,8 +4,7 @@ Types:Enchantment T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a Blood token and conjure a card named Blood Artist onto the battlefield. SVar:TrigToken:DB$ Token | TokenScript$ c_a_blood_draw | SubAbility$ DBMakeCard SVar:DBMakeCard:DB$ MakeCard | Name$ Blood Artist | Zone$ Battlefield -T:Mode$ Sacrificed | ValidCard$ Blood.token+YouCtrl | Execute$ TrigLoseLife | TriggerZones$ Battlefield | TriggerDescription$ Whenever you sacrifice a Blood token, each opponent loses 1 life and you gain 1 life. -SVar:TrigLoseLife:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 1 | SubAbility$ TrigGainLife -SVar:TrigGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 -DeckHas:Ability$Token & Ability$Sacrifice & Ability$LifeGain & Type$Blood -Oracle:When Sanguine Brushstroke enters the battlefield, create a Blood token and conjure a card named Blood Artist onto the battlefield.\nWhenever you sacrifice a Blood token, each opponent loses 1 life and you gain 1 life. +T:Mode$ Sacrificed | ValidCard$ Blood.token+YouCtrl | Execute$ TrigLoseLife | TriggerZones$ Battlefield | TriggerDescription$ Whenever you sacrifice a Blood token, each opponent loses 1 life. +SVar:TrigLoseLife:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 1 +DeckHas:Ability$Token & Ability$Sacrifice & Type$Blood +Oracle:When Sanguine Brushstroke enters the battlefield, create a Blood token and conjure a card named Blood Artist onto the battlefield.\nWhenever you sacrifice a Blood token, each opponent loses 1 life. diff --git a/forge-gui/res/cardsfolder/t/thief_of_blood.txt b/forge-gui/res/cardsfolder/t/thief_of_blood.txt index eb91d9e6128..670eb8b0c1a 100644 --- a/forge-gui/res/cardsfolder/t/thief_of_blood.txt +++ b/forge-gui/res/cardsfolder/t/thief_of_blood.txt @@ -7,7 +7,7 @@ K:ETBReplacement:Other:DBRemoveCounterAll SVar:DBRemoveCounterAll:DB$ RemoveCounterAll | ValidCards$ Permanent | AllCounterTypes$ True | StackDescription$ SpellDescription | SubAbility$ DBPutCounters | RememberAmount$ True | SpellDescription$ As CARDNAME enters the battlefield, remove all counters from all permanents. CARDNAME enters the battlefield with a +1/+1 counter on it for each counter removed this way. SVar:DBPutCounters:DB$ PutCounter | ETB$ True | Defined$ Self | CounterType$ P1P1 | CounterNum$ X | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:X:Count$ChosenNumber +SVar:X:Count$RememberedNumber AI:RemoveDeck:Random DeckHas:Ability$Counters Oracle:Flying\nAs Thief of Blood enters the battlefield, remove all counters from all permanents. Thief of Blood enters the battlefield with a +1/+1 counter on it for each counter removed this way. diff --git a/forge-gui/res/cardsfolder/t/town_razer_tyrant.txt b/forge-gui/res/cardsfolder/t/town_razer_tyrant.txt index a7cc3786464..b33a94714b5 100644 --- a/forge-gui/res/cardsfolder/t/town_razer_tyrant.txt +++ b/forge-gui/res/cardsfolder/t/town_razer_tyrant.txt @@ -3,8 +3,8 @@ ManaCost:2 R R Types:Creature Dragon PT:4/4 K:Flying -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigAnimate | TriggerDescription$ When CARDNAME enters the battlefield, target land you don't control loses all abilities except mana abilities and gains "At the beginning of your upkeep, this permanent deals 2 damage to you unless you sacrifice it." -SVar:TrigAnimate:DB$ Animate | ValidTgts$ Land.YouDontCtrl | TgtPrompt$ Select target land you don't control | RemoveNonManaAbilities$ True | Triggers$ UpkeepShock | Duration$ Permanent +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigAnimate | TriggerDescription$ When CARDNAME enters the battlefield, target nonbasic land you don't control loses all abilities except mana abilities and gains "At the beginning of your upkeep, this permanent deals 2 damage to you unless you sacrifice it." +SVar:TrigAnimate:DB$ Animate | ValidTgts$ Land.nonBasic+YouDontCtrl | TgtPrompt$ Select target nonbasic land you don't control | RemoveNonManaAbilities$ True | Triggers$ UpkeepShock | Duration$ Permanent SVar:UpkeepShock:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ At the beginning of your upkeep, this permanent deals 2 damage to you unless you sacrifice it. SVar:TrigDamage:DB$ DealDamage | Defined$ You | NumDmg$ 2 | UnlessCost$ Sac<1/CARDNAME> | UnlessPayer$ TriggeredPlayer -Oracle:Flying\nWhen Town-razer Tyrant enters the battlefield, target land you don't control loses all abilities except mana abilities and gains "At the beginning of your upkeep, this permanent deals 2 damage to you unless you sacrifice it." +Oracle:Flying\nWhen Town-razer Tyrant enters the battlefield, target nonbasic land you don't control loses all abilities except mana abilities and gains "At the beginning of your upkeep, this permanent deals 2 damage to you unless you sacrifice it." diff --git a/forge-gui/res/cardsfolder/upcoming/chishiro_the_shattered_blade.txt b/forge-gui/res/cardsfolder/upcoming/chishiro_the_shattered_blade.txt new file mode 100644 index 00000000000..09f9ae09291 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/chishiro_the_shattered_blade.txt @@ -0,0 +1,11 @@ +Name:Chishiro, the Shattered Blade +ManaCost:2 R G +Types:Legendary Creature Snake Samurai +PT:4/4 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | ValidCard$ Aura.YouCtrl,Equipment.YouCtrl | Execute$ TrigToken | TriggerDescription$ Whenever an Aura or Equipment enters the battlefield under your control, create a 2/2 red Spirit creature token with menace. +SVar:TrigToken:DB$ Token | TokenScript$ r_2_2_spirit_menace +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigCounters | TriggerDescription$ At the beginning of your end step, put a +1/+1 counter on each modified creature you control. (Equipment, Auras you control, and counters are modifications.) +SVar:TrigCounters:DB$ PutCounterAll | ValidCards$ Creature.YouCtrl+modified | CounterType$ P1P1 | CounterNum$ 1 +DeckHints:Type$Aura|Equipment & Ability$Counters +DeckHas:Ability$Token & Type$Spirit & Ability$Counters +Oracle:Whenever an Aura or Equipment enters the battlefield under your control, create a 2/2 red Spirit creature token with menace.\nAt the beginning of your end step, put a +1/+1 counter on each modified creature you control. (Equipment, Auras you control, and counters are modifications.) diff --git a/forge-gui/res/cardsfolder/upcoming/goro_goro_disciple_of_ryusei.txt b/forge-gui/res/cardsfolder/upcoming/goro_goro_disciple_of_ryusei.txt new file mode 100644 index 00000000000..6b11b0d326f --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/goro_goro_disciple_of_ryusei.txt @@ -0,0 +1,9 @@ +Name:Goro-Goro, Disciple of Ryusei +ManaCost:1 R +Types:Legendary Creature Samurai Goblin +PT:2/2 +A:AB$ PumpAll | Cost$ R | ValidCards$ Creature.YouCtrl | KW$ Haste | SpellDescription$ Creatures you control gain haste until end of turn. +A:AB$ Token | Cost$ 3 R R | TokenScript$ r_5_5_dragon_spirit_flying | IsPresent$ Creature.YouCtrl+attacking+modified | StackDescription$ Create a 5/5 red Dragon Spirit creature token with flying. | SpellDescription$ Create a 5/5 red Dragon Spirit creature token with flying. Activate only if you control an attacking modified creature. +DeckHas:Ability$Token & Type$Dragon|Spirit +DeckHints:Type$Equipment|Aura & Ability$Counters +Oracle:{R}: Creatures you control gain haste until end of turn.\n{3}{R}{R}: Create a 5/5 red Dragon Spirit creature token with flying. Activate only if you control an attacking modified creature. diff --git a/forge-gui/res/editions/Dungeons & Dragons Adventures in the Forgotten Realms.txt b/forge-gui/res/editions/Dungeons & Dragons Adventures in the Forgotten Realms.txt index d429c099b06..b81921e8249 100644 --- a/forge-gui/res/editions/Dungeons & Dragons Adventures in the Forgotten Realms.txt +++ b/forge-gui/res/editions/Dungeons & Dragons Adventures in the Forgotten Realms.txt @@ -426,9 +426,17 @@ FatPackExtraSlots=20 BasicLands, 20 BasicLands+ 402 U Prosperous Innkeeper @Eric Deschamps [rebalanced] +A7 U A-Cloister Gargoyle @Mark Zug A53 M A-Demilich @Daniel Zrom A81 U A-Wizard Class @Marta Nael +A87 M A-Acererak the Archlich @Andrey Kuzinskiy +A102 C A-Fates' Reversal @Alix Branwyn +A115 C A-Precipitous Drop @Gabor Szikszai A180 U A-Druid Class @Svetlin Velinov +A181 M A-Ellywick Tumblestrum @Anna Steinbauer +A183 C A-Find the Path @Lindsey Look +A237 R A-Triumphant Adventurer @Alexander Mokhov +A255 R A-Dungeon Descent @Kasia 'Kafis' Zielińska [dungeons] S Dungeon of the Mad Mage diff --git a/forge-gui/res/editions/Innistrad Crimson Vow.txt b/forge-gui/res/editions/Innistrad Crimson Vow.txt index 6386f084797..8b173bf8aae 100644 --- a/forge-gui/res/editions/Innistrad Crimson Vow.txt +++ b/forge-gui/res/editions/Innistrad Crimson Vow.txt @@ -433,6 +433,9 @@ Prerelease=6 Boosters, 1 RareMythic+ 411 L Mountain @Daria Khlebnikova 412 L Forest @Pig Hands +[rebalanced] +A63 R A-Hullbreaker Horror @Svetlin Velinov + [tokens] b_1_1_slug b_2_2_zombie diff --git a/forge-gui/res/editions/Innistrad Midnight Hunt.txt b/forge-gui/res/editions/Innistrad Midnight Hunt.txt index 792403ff436..66ce4995f7f 100644 --- a/forge-gui/res/editions/Innistrad Midnight Hunt.txt +++ b/forge-gui/res/editions/Innistrad Midnight Hunt.txt @@ -413,6 +413,9 @@ Prerelease=6 Boosters, 1 RareMythic+ 390 U Play with Fire @Svetlin Velinov 391 U Join the Dance @Raoul Vitale +[rebalanced] +A59 M A-Lier, Disciple of the Drowned @Ekaterina Burmak + [tokens] b_1_1_bat_flying b_2_2_zombie_decayed diff --git a/forge-gui/res/editions/Kamigawa Neon Dynasty.txt b/forge-gui/res/editions/Kamigawa Neon Dynasty.txt index 808610a2e10..4639d8bf6ed 100644 --- a/forge-gui/res/editions/Kamigawa Neon Dynasty.txt +++ b/forge-gui/res/editions/Kamigawa Neon Dynasty.txt @@ -5,6 +5,8 @@ Name=Kamigawa: Neon Dynasty Code2=NEO MciCode=neo Type=Expansion +TODO: Make sure Booster is correct closer to release - these are placeholders +Booster=10 Common, 3 Uncommon, 1 RareMythic, 1 BasicLand ScryfallCode=NEO [cards] diff --git a/forge-gui/res/editions/Secret Lair Drop Series.txt b/forge-gui/res/editions/Secret Lair Drop Series.txt index debb33422be..5443727fbe4 100644 --- a/forge-gui/res/editions/Secret Lair Drop Series.txt +++ b/forge-gui/res/editions/Secret Lair Drop Series.txt @@ -362,6 +362,7 @@ ScryfallCode=SLD 383 R Krark's Thumb @Wooden Cyclops 383★ R Krark's Thumb @Wooden Cyclops 384 R Swamp @Jeanne D'Angelo +385 R Island @Jeanne D'Angelo 477 R Path to Exile @Riot Games 478 R Rhystic Study @Riot Games 479 R Duress @Riot Games diff --git a/forge-gui/res/editions/Strixhaven School of Mages.txt b/forge-gui/res/editions/Strixhaven School of Mages.txt index eb875bc6cea..8224ebdbb52 100644 --- a/forge-gui/res/editions/Strixhaven School of Mages.txt +++ b/forge-gui/res/editions/Strixhaven School of Mages.txt @@ -408,6 +408,9 @@ ScryfallCode=STX 381 U Rip Apart @Anna Podedworna 382 U Decisive Denial @Lorenzo Mastroianni +[rebalanced] +A41 U A-Divide by Zero @Liiga Smilshkalne + [lesson] 2 Environmental Sciences 2 Expanded Anatomy diff --git a/forge-gui/res/editions/War of the Spark.txt b/forge-gui/res/editions/War of the Spark.txt index 67590db9d57..32a35b13ba8 100644 --- a/forge-gui/res/editions/War of the Spark.txt +++ b/forge-gui/res/editions/War of the Spark.txt @@ -326,6 +326,9 @@ ScryfallCode=WAR 235★ U Samut, Tyrant Smasher @Norikatsu Miyoshi 236★ U Vraska, Swarm's Eminence @Ryota Murayama +[rebalanced] +A221 R A-Teferi, Time Raveler @Chris Rallis + [tokens] wubrg_2_2_citizen b_0_0_zombie_army diff --git a/forge-gui/res/formats/Casual/Pauper.txt b/forge-gui/res/formats/Casual/Pauper.txt index 20b8ecb3e34..b7f46f19636 100644 --- a/forge-gui/res/formats/Casual/Pauper.txt +++ b/forge-gui/res/formats/Casual/Pauper.txt @@ -4,4 +4,4 @@ Order:108 Subtype:Custom Type:Casual Rarities:L, C -Banned:Arcum's Astrolabe; Chatterstorm; Cloud of Faeries; Cloudpost; Cranial Plating; Daze; Expedition Map; Empty the Warrens; Fall from Favor; Frantic Search; Gitaxian Probe; Grapeshot; Gush; High Tide; Hymn to Tourach; Invigorate; Mystic Sanctuary; Peregrine Drake; Sinkhole; Sojourner's Companion; Temporal Fissure; Treasure Cruise +Banned:Arcum's Astrolabe; Atog; Bonder's Ornament; Chatterstorm; Cloud of Faeries; Cloudpost; Cranial Plating; Daze; Expedition Map; Empty the Warrens; Fall from Favor; Frantic Search; Gitaxian Probe; Grapeshot; Gush; High Tide; Hymn to Tourach; Invigorate; Mystic Sanctuary; Peregrine Drake; Prophetic Prism; Sinkhole; Sojourner's Companion; Temporal Fissure; Treasure Cruise diff --git a/forge-gui/res/formats/Sanctioned/Historic.txt b/forge-gui/res/formats/Sanctioned/Historic.txt index 407bdd5e586..1d5459e7b29 100644 --- a/forge-gui/res/formats/Sanctioned/Historic.txt +++ b/forge-gui/res/formats/Sanctioned/Historic.txt @@ -4,5 +4,5 @@ Type:Digital Subtype:Arena Effective:2019-11-21 Order:142 -Sets:XLN, RIX, DOM, M19, GRN, G18, RNA, WAR, M20, ELD, HA1, THB, HA2, IKO, HA3, M21, JMP, AKR, ZNR, KLR, KHM, HA4, STX, STA, HA5, AFR, J21, MID, VOW -Banned:Agent of Treachery; Brainstorm; Channel; Counterspell; Dark Ritual; Demonic Tutor; Field of the Dead; Fires of Invention; Lightning Bolt; Natural Order; Nexus of Fate; Oko, Thief of Crowns; Omnath, Locus of Creation; Once Upon a Time; Swords to Plowshares; Teferi, Time Raveler; Thassa's Oracle; Tibalt's Trickery; Time Warp; Uro, Titan of Nature's Wrath; Veil of Summer; Wilderness Reclamation; Winota, Joiner of Forces +Sets:XLN, RIX, DOM, M19, GRN, G18, RNA, WAR, M20, ELD, HA1, THB, HA2, IKO, HA3, M21, JMP, AKR, ANB, ZNR, KLR, KHM, HA4, STX, STA, HA5, AFR, J21, MID, VOW, Y22 +Banned:Agent of Treachery; Brainstorm; Channel; Counterspell; Dark Ritual; Demonic Tutor; Field of the Dead; Fires of Invention; Lightning Bolt; Memory Lapse; Natural Order; Nexus of Fate; Oko, Thief of Crowns; Once Upon a Time; Swords to Plowshares; Thassa's Oracle; Tibalt's Trickery; Time Warp; Uro, Titan of Nature's Wrath; Veil of Summer; Wilderness Reclamation; Winota, Joiner of Forces diff --git a/forge-gui/res/formats/Sanctioned/Legacy.txt b/forge-gui/res/formats/Sanctioned/Legacy.txt index 252faccf7ae..54ab4c006cf 100644 --- a/forge-gui/res/formats/Sanctioned/Legacy.txt +++ b/forge-gui/res/formats/Sanctioned/Legacy.txt @@ -4,4 +4,4 @@ Order:105 Subtype:Legacy Type:Sanctioned Sets:7ED, 9ED, ORI, M14, M15, 6ED, 8ED, M11, 3ED, M10, M12, 10E, M13, G18, M21, M20, M19, 5ED, 2ED, 4ED, LEB, LEA, 5DN, SOM, KTK, THS, DIS, JOU, MOR, TMP, SOI, FEM, USG, ALL, ROE, EXO, TSP, LRW, TOR, ALA, RIX, DGM, DKA, MBS, AER, RNA, GTC, CSP, HML, NPH, OGW, ZNR, EMN, UDS, SHM, BNG, SOK, EVE, INV, THB, DOM, NMS, VIS, WAR, GRN, PCY, SCG, MRD, XLN, ONS, IKO, MMQ, CHK, ULG, AKH, MIR, ISD, AVR, KLD, APC, RTR, WWK, PLC, HOU, LEG, AFR, ARN, ICE, STX, LGN, ARB, KHM, CFX, TSB, ZEN, ELD, JUD, GPT, BFZ, BOK, DTK, FRF, FUT, WTH, ODY, RAV, ATQ, DRK, PLS, STH, DST, TD2, HA1, ME4, HA3, HA2, HA5, HA4, MED, ANB, ME3, KLR, PZ2, ANA, PRM, PZ1, AJMP, ME2, TD1, TD0, TPR, VMA, AKR, MBP, PZEN, PGTW, PL21, PFUT, PWAR, PAL01, PJUD, PAL00, PTKDF, PWOR, PWP12, PSTH, POGW, PFRF, PG07, PSUS, PUST, J18, PWP10, PAL02, PAL03, PWP11, J19, PGRN, PM10, PDP14, PRTR, PMPS06, PBNG, PJ21, G09, PNPH, PM15, PAL06, G08, PDST, J20, PMBS, PMPS07, PEXO, PDOM, PONS, PRW2, PMPS11, PMPS, PM19, PWWK, PCEL, PAL04, PAL05, PMPS10, PDTK, PALP, F10, F04, PMOR, PAL99, PEMN, PCNS, PPLC, PRAV, PPP1, PI14, PXLN, PF20, PTSP, F05, F11, PSCG, PBOOK, F07, F13, PODY, PM12, P08, PSS1, P2HG, P09, PTOR, PDP13, F12, F06, PALA, PXTC, F02, F16, PHOU, PSOM, PI13, PCON, PDGM, PIDW, PMRD, PRNA, P9ED, PHEL, F17, F03, PURL, F15, F01, PWOS, PPC1, PBOK, PTMP, PS19, PS18, PF19, PGPT, PCHK, FNM, F14, PISD, PAKH, PDP15, PRIX, PS15, PPCY, OLGC, OVNT, PLGN, PS14, P03, PDTP, PM14, FS, PPLS, MPR, PKTK, PS16, PRWK, PS17, PBFZ, PSS2, PINV, G03, P8ED, PARL, P04, P10, PSDC, JGP, G99, WW, P11, P05, PDIS, PROE, PDP10, F08, P10E, PELP, PMH1, P07, P5DN, PGRU, SHC, PM11, P06, PUSG, PCMP, PULG, F09, PUDS, PARB, DRC94, PMPS09, PORI, J12, G06, PMMQ, G07, J13, PMPS08, PM20, PSOI, PJSE, G05, G11, PNAT, PSOK, PEVE, PRED, G10, G04, PSHM, PPRO, PAPC, PJJT, ARENA, PKLD, G00, J14, PLGM, P15A, PCSP, PWPN, PJAS, PWP21, PWP09, PDKA, PNEM, PPTK, J15, G01, PG08, PLRW, PMEI, PM13, PHJ, PGTC, J17, PRES, PWCQ, PJOU, PDP12, PAER, PAVR, PTHS, G02, J16, PSUM, PGPX, UGF, PSS3, MM2, MM3, MB1, FMB1, A25, 2XM, MMA, PLIST, CHR, EMA, IMA, TSR, UMA, PUMA, E02, DPA, ATH, MD1, GK1, GK2, CST, BRB, BTD, DKM, FVE, V17, V13, STA, MPS_RNA, V16, SLD, V12, CC1, MPS_GRN, DRB, FVR, SS3, SS1, MPS_AKH, FVL, V15, MPS_KLD, ZNE, PDS, SS2, PD3, SLU, V14, PD2, EXP, MPS_WAR, DDQ, DDE, GS1, DDS, DDU, DD1, DDL, DDF, DDP, DD2, DDR, DDH, DDT, DDK, DDG, DDC, DDM, DDJ, DDO, GVL, JVC, DDI, DVD, DDN, EVG, DDD, C18, C19, C21, C20, C13, CMA, C14, C15, KHC, ZNC, AFC, C17, C16, COM, CM1, CM2, PO2, S99, W16, W17, S00, PTK, CP3, POR, CP1, CP2, CMR, MH2, H1R, CNS, BBD, MH1, CN2, JMP, PCA, GNT, ARC, GN2, PC2, E01, HOP, PLG20, PLG21, CC2, MID, MIC, VOW, VOC -Banned:Adriana's Valor; Advantageous Proclamation; Arcum's Astrolabe; Assemble the Rank and Vile; Backup Plan; Brago's Favor; Deathrite Shaman; Double Stroke; Dreadhorde Arcanist; Echoing Boon; Emissary's Ploy; Gitaxian Probe; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Incendiary Dissent; Iterative Analysis; Lurrus of the Dream-Den; Muzzio's Preparations; Natural Unity; Oko, Thief of Crowns; Power Play; Secret Summoning; Secrets of Paradise; Sentinel Dispatch; Sovereign's Realm; Summoner's Bond; Underworld Breach; Unexpected Potential; Weight Advantage; Worldknit; Amulet of Quoz; Bronze Tablet; Contract from Below; Darkpact; Demonic Attorney; Jeweled Bird; Rebirth; Tempest Efreet; Timmerian Fiends; Ancestral Recall; Balance; Bazaar of Baghdad; Black Lotus; Channel; Chaos Orb; Demonic Consultation; Demonic Tutor; Dig Through Time; Earthcraft; Falling Star; Fastbond; Flash; Frantic Search; Goblin Recruiter; Gush; Hermit Druid; Imperial Seal; Library of Alexandria; Mana Crypt; Mana Drain; Mana Vault; Memory Jar; Mental Misstep; Mind Twist; Mind's Desire; Mishra's Workshop; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Mystical Tutor; Necropotence; Oath of Druids; Sensei's Divining Top; Shahrazad; Skullclamp; Sol Ring; Strip Mine; Survival of the Fittest; Time Vault; Time Walk; Timetwister; Tinker; Tolarian Academy; Treasure Cruise; Vampiric Tutor; Wheel of Fortune; Windfall; Wrenn and Six; Yawgmoth's Bargain; Yawgmoth's Will; Zirda, the Dawnwaker; Cleanse; Crusade; Imprison; Invoke Prejudice; Jihad; Pradesh Gypsies; Stone-Throwing Devils +Banned:Adriana's Valor; Advantageous Proclamation; Arcum's Astrolabe; Assemble the Rank and Vile; Backup Plan; Brago's Favor; Deathrite Shaman; Double Stroke; Dreadhorde Arcanist; Echoing Boon; Emissary's Ploy; Gitaxian Probe; Hired Heist; Hold the Perimeter; Hymn of the Wilds; Immediate Action; Incendiary Dissent; Iterative Analysis; Lurrus of the Dream-Den; Muzzio's Preparations; Natural Unity; Oko, Thief of Crowns; Power Play; Ragavan, Nimble Pilferer; Secret Summoning; Secrets of Paradise; Sentinel Dispatch; Sovereign's Realm; Summoner's Bond; Underworld Breach; Unexpected Potential; Weight Advantage; Worldknit; Amulet of Quoz; Bronze Tablet; Contract from Below; Darkpact; Demonic Attorney; Jeweled Bird; Rebirth; Tempest Efreet; Timmerian Fiends; Ancestral Recall; Balance; Bazaar of Baghdad; Black Lotus; Channel; Chaos Orb; Demonic Consultation; Demonic Tutor; Dig Through Time; Earthcraft; Falling Star; Fastbond; Flash; Frantic Search; Goblin Recruiter; Gush; Hermit Druid; Imperial Seal; Library of Alexandria; Mana Crypt; Mana Drain; Mana Vault; Memory Jar; Mental Misstep; Mind Twist; Mind's Desire; Mishra's Workshop; Mox Emerald; Mox Jet; Mox Pearl; Mox Ruby; Mox Sapphire; Mystical Tutor; Necropotence; Oath of Druids; Sensei's Divining Top; Shahrazad; Skullclamp; Sol Ring; Strip Mine; Survival of the Fittest; Time Vault; Time Walk; Timetwister; Tinker; Tolarian Academy; Treasure Cruise; Vampiric Tutor; Wheel of Fortune; Windfall; Wrenn and Six; Yawgmoth's Bargain; Yawgmoth's Will; Zirda, the Dawnwaker; Cleanse; Crusade; Imprison; Invoke Prejudice; Jihad; Pradesh Gypsies; Stone-Throwing Devils diff --git a/forge-gui/res/formats/Sanctioned/Standard.txt b/forge-gui/res/formats/Sanctioned/Standard.txt index dc8bf11699e..93bc6101a2a 100644 --- a/forge-gui/res/formats/Sanctioned/Standard.txt +++ b/forge-gui/res/formats/Sanctioned/Standard.txt @@ -4,4 +4,4 @@ Order:101 Subtype:Standard Type:Sanctioned Sets:ZNR, KHM, STX, AFR, MID, VOW -Banned:Omnath, Locus of Creation +Banned:Alrund's Epiphany; Divide by Zero; Faceless Haven; Omnath, Locus of Creation diff --git a/forge-gui/res/lists/net-decks-brawl.txt b/forge-gui/res/lists/net-decks-brawl.txt index bce415a4679..ad9e5359945 100644 --- a/forge-gui/res/lists/net-decks-brawl.txt +++ b/forge-gui/res/lists/net-decks-brawl.txt @@ -9,4 +9,4 @@ Feature Article | https://downloads.cardforge.org/decks/feature-brawl.zip How to Build | https://downloads.cardforge.org/decks/howtobuild-brawl.zip Much Abrew About Nothing | https://downloads.cardforge.org/decks/muchabrewaboutnothing-brawl.zip Ready to Brawl? | https://downloads.cardforge.org/decks/readytobrawl.zip -Ways to Play | https://downloads.cardforge.org/decks/waystoplay-brawl.zip \ No newline at end of file +Ways to Play | https://downloads.cardforge.org/decks/waystoplay-brawl.zip diff --git a/forge-gui/res/tokenscripts/r_2_2_spirit_menace.txt b/forge-gui/res/tokenscripts/r_2_2_spirit_menace.txt new file mode 100644 index 00000000000..7d7cfbdba9f --- /dev/null +++ b/forge-gui/res/tokenscripts/r_2_2_spirit_menace.txt @@ -0,0 +1,7 @@ +Name:Spirit Token +ManaCost:no cost +Colors:red +Types:Creature Spirit +PT:2/2 +K:Menace +Oracle:Menace diff --git a/forge-gui/res/tokenscripts/r_5_5_dragon_spirit_flying.txt b/forge-gui/res/tokenscripts/r_5_5_dragon_spirit_flying.txt new file mode 100644 index 00000000000..8dea4158881 --- /dev/null +++ b/forge-gui/res/tokenscripts/r_5_5_dragon_spirit_flying.txt @@ -0,0 +1,7 @@ +Name:Dragon Spirit Token +ManaCost:no cost +Types:Creature Dragon Spirit +Colors:red +K:Flying +PT:5/5 +Oracle:Flying diff --git a/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java b/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java index bf3af673ae4..f19ef89d0be 100644 --- a/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java +++ b/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java @@ -17,10 +17,8 @@ import forge.card.ColorSet; import forge.card.MagicColor; import forge.card.mana.ManaCostShard; import forge.game.GameView; -import forge.game.card.CardView; import forge.game.card.CardView.CardStateView; import forge.game.zone.ZoneType; -import forge.game.card.CounterType; import forge.item.InventoryItemFromSet; import forge.item.PaperCard; import forge.item.PreconDeck; diff --git a/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java b/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java index 33e4d8aee94..c7f5f3ab8d3 100644 --- a/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java +++ b/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java @@ -429,7 +429,7 @@ public final class CardScriptParser { "leastPower", "leastToughness", "greatestCMC", "greatestRememberedCMC", "lowestRememberedCMC", "lowestCMC", "enchanted", "unenchanted", "enchanting", "equipped", "unequipped", - "equipping", "token", "nonToken", "hasXCost", "suspended", + "equipping", "modified", "token", "nonToken", "hasXCost", "suspended", "delved", "attacking", "attackingYou", "notattacking", "attackedBySourceThisCombat", "blocking", "blockingSource", "blockingCreatureYouCtrl", "blockingRemembered",