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",