From 08434c0dc531180e77f7d846259a65b779ca3b22 Mon Sep 17 00:00:00 2001
From: Simisays <67333662+Simisays@users.noreply.github.com>
Date: Sat, 15 Jul 2023 20:28:47 +0200
Subject: [PATCH 1/7] update
---
.../common/maps/tileset/buildingsbosses.atlas | 17 ++++++++-
.../common/maps/tileset/buildingsbosses.png | Bin 89420 -> 88105 bytes
.../common/world/points_of_interest.json | 36 +++++++++---------
3 files changed, 34 insertions(+), 19 deletions(-)
diff --git a/forge-gui/res/adventure/common/maps/tileset/buildingsbosses.atlas b/forge-gui/res/adventure/common/maps/tileset/buildingsbosses.atlas
index 53e8ad00ba8..f31b3130f98 100644
--- a/forge-gui/res/adventure/common/maps/tileset/buildingsbosses.atlas
+++ b/forge-gui/res/adventure/common/maps/tileset/buildingsbosses.atlas
@@ -41,4 +41,19 @@ MageTower
size: 26, 49
Skep
xy: 110,281
- size: 37, 33
\ No newline at end of file
+ size: 37, 33
+MageTowerBlue
+ xy: 2,327
+ size: 32, 32
+MageTowerRed
+ xy: 36,328
+ size: 32, 32
+MageTowerBlack
+ xy: 63,328
+ size: 32, 32
+MageTowerGreen
+ xy: 92,328
+ size: 32, 32
+MageTowerWhite
+ xy: 121,328
+ size: 32, 32
\ No newline at end of file
diff --git a/forge-gui/res/adventure/common/maps/tileset/buildingsbosses.png b/forge-gui/res/adventure/common/maps/tileset/buildingsbosses.png
index 27ff37c3a25b0dc315042d229c97fc573fd81a29..0ef3a70fc383298eba7fee6c8dc343a571738d9b 100644
GIT binary patch
delta 10096
zcmbVvWmFwevnB2pLXhAZB)CiPAi)zLxFxvf;?@wH;O=h0-8Hyd(2Kisfs0;b$Tw?d
z-pqQxrhoM6ea@~^wW{{1T0Po={JRP{nihZ?@KD!s`fTh<qiE2@vH$d*ap~|19gObEV`w=^SW!!R`
SJ77LjlR`Wnq3_k??W_e-`&Den`+C?FMH%I
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
L^}0;yebD~{QHAZs
diff --git a/forge-gui/res/adventure/common/world/points_of_interest.json b/forge-gui/res/adventure/common/world/points_of_interest.json
index 118acbf1ece..3d404110e68 100644
--- a/forge-gui/res/adventure/common/world/points_of_interest.json
+++ b/forge-gui/res/adventure/common/world/points_of_interest.json
@@ -2068,7 +2068,7 @@
"type": "dungeon",
"count": 3,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerRed",
"map": "../common/maps/map/magetower/magetower_1.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2084,7 +2084,7 @@
"type": "dungeon",
"count": 3,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerBlack",
"map": "../common/maps/map/magetower/magetower_2.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2100,7 +2100,7 @@
"type": "dungeon",
"count": 3,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerRed",
"map": "../common/maps/map/magetower/magetower_3.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2116,7 +2116,7 @@
"type": "dungeon",
"count": 3,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerWhite",
"map": "../common/maps/map/magetower/magetower_4.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2132,7 +2132,7 @@
"type": "dungeon",
"count": 3,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerGreen",
"map": "../common/maps/map/magetower/magetower_5.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2148,7 +2148,7 @@
"type": "dungeon",
"count": 3,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerBlack",
"map": "../common/maps/map/magetower/magetower_6.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2163,8 +2163,8 @@
"name": "MageTowerC8",
"type": "dungeon",
"count": 3,
- "spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "spriteAtlas": "../common/maps/tileset/buildings.atlas",
+ "sprite": "MageTowerBlue",
"map": "../common/maps/map/magetower/magetower_8.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2180,7 +2180,7 @@
"type": "dungeon",
"count": 1,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerBlue",
"map": "../common/maps/map/magetower/magetower_13.tmx",
"radiusFactor": 0.2,
"questTags": [
@@ -2196,7 +2196,7 @@
"type": "dungeon",
"count": 3,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerBlue",
"map": "../common/maps/map/magetower/magetower_14.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2212,7 +2212,7 @@
"type": "dungeon",
"count": 2,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerBlue",
"map": "../common/maps/map/magetower/magetower_1.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2228,7 +2228,7 @@
"type": "dungeon",
"count": 2,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerBlack",
"map": "../common/maps/map/magetower/magetower_2.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2244,7 +2244,7 @@
"type": "dungeon",
"count": 2,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerRed",
"map": "../common/maps/map/magetower/magetower_3.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2260,7 +2260,7 @@
"type": "dungeon",
"count": 2,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerWhite",
"map": "../common/maps/map/magetower/magetower_4.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2276,7 +2276,7 @@
"type": "dungeon",
"count": 2,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerGreen",
"map": "../common/maps/map/magetower/magetower_5.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2292,7 +2292,7 @@
"type": "dungeon",
"count": 2,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerBlack",
"map": "../common/maps/map/magetower/magetower_6.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2308,7 +2308,7 @@
"type": "dungeon",
"count": 2,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerBlue",
"map": "../common/maps/map/magetower/magetower_8.tmx",
"radiusFactor": 0.8,
"questTags": [
@@ -2324,7 +2324,7 @@
"type": "dungeon",
"count": 2,
"spriteAtlas": "../common/maps/tileset/buildingsbosses.atlas",
- "sprite": "MageTower",
+ "sprite": "MageTowerBlue",
"map": "../common/maps/map/magetower/magetower_14.tmx",
"radiusFactor": 0.8,
"questTags": [
From 51dbd2209d60a5b3d90389e69f05677308b77fb2 Mon Sep 17 00:00:00 2001
From: Anthony Calosa
Date: Mon, 17 Jul 2023 09:33:15 +0800
Subject: [PATCH 2/7] update translation
---
forge-game/src/main/java/forge/game/card/CardView.java | 9 +++++++--
forge-gui/res/languages/de-DE.properties | 2 ++
forge-gui/res/languages/en-US.properties | 2 ++
forge-gui/res/languages/es-ES.properties | 2 ++
forge-gui/res/languages/fr-FR.properties | 2 ++
forge-gui/res/languages/it-IT.properties | 2 ++
forge-gui/res/languages/ja-JP.properties | 2 ++
forge-gui/res/languages/pt-BR.properties | 2 ++
forge-gui/res/languages/zh-CN.properties | 2 ++
9 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java
index 1d662f1a684..0729f6de972 100644
--- a/forge-game/src/main/java/forge/game/card/CardView.java
+++ b/forge-game/src/main/java/forge/game/card/CardView.java
@@ -1274,8 +1274,13 @@ public class CardView extends GameEntityView {
String rulesText = null;
if (type.isVanguard() && rules != null) {
- rulesText = "Hand Modifier: " + rules.getHand() +
- "\r\nLife Modifier: " + rules.getLife();
+ boolean decHand = rules.getHand() < 0;
+ boolean decLife = rules.getLife() < 0;
+ String handSize = Localizer.getInstance().getMessageorUseDefault("lblHandSize", "Hand Size")
+ + (!decHand ? ": +" : ": ") + rules.getHand();
+ String startingLife = Localizer.getInstance().getMessageorUseDefault("lblStartingLife", "Starting Life")
+ + (!decLife ? ": +" : ": ") + rules.getLife();
+ rulesText = handSize + "\r\n" + startingLife;
}
set(TrackableProperty.RulesText, rulesText);
}
diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties
index c7a023e0be1..1a49029b78c 100644
--- a/forge-gui/res/languages/de-DE.properties
+++ b/forge-gui/res/languages/de-DE.properties
@@ -2237,6 +2237,8 @@ lblSelectThisCardConfirm=Wähle diese Karte?
#CardView.java
lblMainGame=Hauptspiel
lblSubgame=Unterspiel (Auslöser {0})
+lblHandSize=Handgröße
+lblStartingLife=Leben beginnen
#PlayerView.java
lblCommanderCastCard=Wurde bereits {0} mal aus der Kommandozone gespielt
lblCommanderCastPlayer={0} spielte {1} mal aus der Kommandozone
diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties
index 4f49f4eb537..3db1e4d8ba2 100644
--- a/forge-gui/res/languages/en-US.properties
+++ b/forge-gui/res/languages/en-US.properties
@@ -2242,6 +2242,8 @@ lblSelectThisCardConfirm=Select this card?
#CardView.java
lblMainGame=Main game
lblSubgame=Subgame ({0} parent)
+lblHandSize=Hand Size
+lblStartingLife=Starting Life
#PlayerView.java
lblCommanderCastCard=Cast from command zone {0} times
lblCommanderCastPlayer={0} cast from command zone {1} times
diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties
index 44fe1b33308..8f2900058ac 100644
--- a/forge-gui/res/languages/es-ES.properties
+++ b/forge-gui/res/languages/es-ES.properties
@@ -2238,6 +2238,8 @@ lblSelectThisCardConfirm=¿Selecciona esta carta?
#CardView.java
lblMainGame=Juego principal
lblSubgame=Subjuego (padre {0})
+lblHandSize=Tamaño de la mano
+lblStartingLife=La vida inicial
#PlayerView.java
lblCommanderCastCard=Lanzado desde la zona de comandante {0} veces
lblCommanderCastPlayer={0} lanzado desde la zona de comandante {1} veces
diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties
index d7db71bdacc..b40c7ecd6ad 100644
--- a/forge-gui/res/languages/fr-FR.properties
+++ b/forge-gui/res/languages/fr-FR.properties
@@ -2240,6 +2240,8 @@ lblSelectThisCardConfirm=Sélectionner cette carte ?
#CardView.java
lblMainGame=Jeu principal
lblSubgame=Sous-jeu ({0} parent)
+lblHandSize=Taille de la main
+lblStartingLife=Début de la vie
#PlayerView.java
lblCommanderCastCard=Lancer depuis la zone de commande {0} fois
lblCommanderCastPlayer={0} lancer de la zone de commande {1} fois
diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties
index 36675f409cb..ec00c889d38 100644
--- a/forge-gui/res/languages/it-IT.properties
+++ b/forge-gui/res/languages/it-IT.properties
@@ -2237,6 +2237,8 @@ lblSelectThisCardConfirm=Vuoi scegliere questa carta?
#CardView.java
lblMainGame=Gioco principale
lblSubgame=Sottopartita (da {0})
+lblHandSize=Dimensione delle mani
+lblStartingLife=La vita iniziale
#PlayerView.java
lblCommanderCastCard=Lanciato dalla zona di comando {0} volte
lblCommanderCastPlayer={0} è stato lanciato dalla zona di comando {1} volte
diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties
index 8f8ffe0ad14..ce172950b02 100644
--- a/forge-gui/res/languages/ja-JP.properties
+++ b/forge-gui/res/languages/ja-JP.properties
@@ -2237,6 +2237,8 @@ lblSelectThisCardConfirm=このカードを選択しますか?
#CardView.java
lblMainGame=メインゲーム
lblSubgame={0}つ上のサブゲーム
+lblHandSize=ハンドサイズ
+lblStartingLife=人生を始める
#PlayerView.java
lblCommanderCastCard=コマンド領域からキャスト:{0}回
lblCommanderCastPlayer={0}が {1}回コマンド領域からキャストした
diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties
index cbf5491e4d7..cd5185a5336 100644
--- a/forge-gui/res/languages/pt-BR.properties
+++ b/forge-gui/res/languages/pt-BR.properties
@@ -2304,6 +2304,8 @@ lblSelectThisCardConfirm=Escolher este cartão?
#CardView.java
lblMainGame=Jogo Principal
lblSubgame=Subjogo ({0} pai)
+lblHandSize=Tamanho da mão
+lblStartingLife=Começando a vida
#PlayerView.java
lblCommanderCastCard=Conjurado da zona de comando {0} vezes
lblCommanderCastPlayer={0} conjurou da zona de comando {1} vezes
diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties
index 6fb1807dd17..76b12f413e7 100644
--- a/forge-gui/res/languages/zh-CN.properties
+++ b/forge-gui/res/languages/zh-CN.properties
@@ -2242,6 +2242,8 @@ lblSelectThisCardConfirm=选择这张牌?
#CardView.java
lblMainGame=主游戏
lblSubgame=子游戏({0}个父游戏)
+lblHandSize=手尺寸
+lblStartingLife=开始生活
#PlayerView.java
lblCommanderCastCard=从指挥官区域释放过{0}次
lblCommanderCastPlayer={0}从指挥官区域释放过{1}次
From 65259ab6bf6e6e2254615c201e1d3ca15e7017d2 Mon Sep 17 00:00:00 2001
From: Valerio Maggio
Date: Mon, 17 Jul 2023 07:52:00 +0100
Subject: [PATCH 3/7] Update Premodern Format Banlist July 23
---
forge-gui/res/formats/Casual/Premodern.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/forge-gui/res/formats/Casual/Premodern.txt b/forge-gui/res/formats/Casual/Premodern.txt
index 3213d670fa5..0decb40c04a 100644
--- a/forge-gui/res/formats/Casual/Premodern.txt
+++ b/forge-gui/res/formats/Casual/Premodern.txt
@@ -3,4 +3,4 @@ Name:Premodern
Order:106
Type:Casual
Sets:4ED, ICE, CHR, HML, ALL, MIR, VIS, 5ED, WTH, TMP, STH, EXO, USG, ULG, 6ED, UDS, MMQ, NMS, PCY, INV, PLS, 7ED, APC, ODY, TOR, JUD, ONS, LGN, SCG
-Banned:Amulet of Quoz; Balance; Brainstorm; Bronze Tablet; Channel; Demonic Consultation; Earthcraft; Entomb; Flash; Force of Will; Goblin Recruiter; Grim Monolith; Jeweled Bird; Mana Vault; Memory Jar; Mind Twist; Mind's Desire; Mystical Tutor; Necropotence; Rebirth; Strip Mine; Tempest Efreet; Tendrils of Agony; Time Spiral; Timmerian Fiends; Tolarian Academy; Vampiric Tutor; Windfall; Worldgorger Dragon; Yawgmoth's Bargain; Yawgmoth's Will
\ No newline at end of file
+Banned:Amulet of Quoz; Balance; Brainstorm; Bronze Tablet; Channel; Demonic Consultation; Earthcraft; Entomb; Flash; Force of Will; Goblin Recruiter; Grim Monolith; Jeweled Bird; Land Tax; Mana Vault; Memory Jar; Mind Twist; Mind's Desire; Mystical Tutor; Necropotence; Rebirth; Strip Mine; Tempest Efreet; Tendrils of Agony; Time Spiral; Timmerian Fiends; Tolarian Academy; Vampiric Tutor; Windfall; Worldgorger Dragon; Yawgmoth's Bargain; Yawgmoth's Will
\ No newline at end of file
From 44388fe3a2d2e773f725975135a40895b3517184 Mon Sep 17 00:00:00 2001
From: Northmoc <103371817+Northmoc@users.noreply.github.com>
Date: Mon, 17 Jul 2023 03:50:33 -0400
Subject: [PATCH 4/7] MAT: ob_nixilis_captive_kingpin.txt + support (#3023)
* old card tweaks
* MAT: ob_nixilis_captive_kingpin.txt + support
* Single damage event always gets processed into single life loss too
* Some unless cost are simultaneous
---
.../src/main/java/forge/game/GameAction.java | 16 ++-
.../java/forge/game/ability/AbilityKey.java | 15 ++-
.../ability/effects/LifeExchangeEffect.java | 26 +++-
.../effects/LifeExchangeVariantEffect.java | 17 ++-
.../game/ability/effects/LifeLoseEffect.java | 17 ++-
.../game/ability/effects/LifeSetEffect.java | 93 ++++++++++----
.../ability/effects/RepeatEachEffect.java | 16 ++-
.../java/forge/game/card/CardFactory.java | 2 +-
.../java/forge/game/phase/PhaseHandler.java | 10 +-
.../main/java/forge/game/player/Player.java | 27 ++--
.../forge/game/spellability/SpellAbility.java | 13 ++
.../game/trigger/TriggerLifeLostAll.java | 117 ++++++++++++++++++
.../java/forge/game/trigger/TriggerType.java | 1 +
forge-gui/res/cardsfolder/f/forge_devil.txt | 5 +-
.../res/cardsfolder/h/hordewing_skaab.txt | 2 +-
forge-gui/res/cardsfolder/k/killing_wave.txt | 10 +-
.../cardsfolder/n/night_market_lookout.txt | 2 +-
.../res/cardsfolder/r/reverse_the_sands.txt | 2 +-
.../res/cardsfolder/t/tree_of_perdition.txt | 2 +-
.../upcoming/ob_nixilis_captive_kingpin.txt | 14 +++
20 files changed, 343 insertions(+), 64 deletions(-)
create mode 100644 forge-game/src/main/java/forge/game/trigger/TriggerLifeLostAll.java
create mode 100644 forge-gui/res/cardsfolder/upcoming/ob_nixilis_captive_kingpin.txt
diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java
index e016bd951f8..799a5b06142 100644
--- a/forge-game/src/main/java/forge/game/GameAction.java
+++ b/forge-game/src/main/java/forge/game/GameAction.java
@@ -2436,13 +2436,23 @@ public class GameAction {
damageMap.triggerExcessDamage(isCombat, lethalDamage, game, cause, lkiCache);
// lose life simultaneously
- if (isCombat) {
- for (Player p : game.getPlayers()) {
- p.dealCombatDamage();
+ Map lifeLostAllDamageMap = Maps.newHashMap();
+ for (Player p : game.getPlayers()) {
+ int lost = p.processDamage();
+ if (lost > 0) {
+ lifeLostAllDamageMap.put(p, lost);
}
+ }
+
+ if (isCombat) {
game.getTriggerHandler().runWaitingTriggers();
}
+ if (!lifeLostAllDamageMap.isEmpty()) { // Run triggers if any player actually lost life
+ final Map runParams = AbilityKey.mapFromPIMap(lifeLostAllDamageMap);
+ game.getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runParams, false);
+ }
+
if (cause != null) {
// Remember objects as needed
final Card sourceLKI = game.getChangeZoneLKIInfo(cause.getHostCard());
diff --git a/forge-game/src/main/java/forge/game/ability/AbilityKey.java b/forge-game/src/main/java/forge/game/ability/AbilityKey.java
index 9dd6cccaa9b..3722b796c20 100644
--- a/forge-game/src/main/java/forge/game/ability/AbilityKey.java
+++ b/forge-game/src/main/java/forge/game/ability/AbilityKey.java
@@ -1,13 +1,12 @@
package forge.game.ability;
-import java.util.EnumMap;
-import java.util.Map;
-
import forge.game.GameEntity;
import forge.game.card.Card;
-
import forge.game.player.Player;
+import java.util.EnumMap;
+import java.util.Map;
+
/**
* Keys for Ability parameter maps.
*/
@@ -84,6 +83,7 @@ public enum AbilityKey {
LastStateGraveyard("LastStateGraveyard"),
LifeAmount("LifeAmount"), //TODO confirm that this and LifeGained can be merged
LifeGained("LifeGained"),
+ Map("Map"),
Mana("Mana"),
MergedCards("MergedCards"),
Mode("Mode"),
@@ -193,4 +193,11 @@ public enum AbilityKey {
runParams.put(Affected, gameEntity);
return runParams;
}
+
+ public static Map mapFromPIMap(Map map) {
+ final Map runParams = newMap();
+
+ runParams.put(Map, map);
+ return runParams;
+ }
}
diff --git a/forge-game/src/main/java/forge/game/ability/effects/LifeExchangeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/LifeExchangeEffect.java
index 5927cd04d8a..c179f83b10d 100644
--- a/forge-game/src/main/java/forge/game/ability/effects/LifeExchangeEffect.java
+++ b/forge-game/src/main/java/forge/game/ability/effects/LifeExchangeEffect.java
@@ -1,11 +1,15 @@
package forge.game.ability.effects;
-import java.util.List;
-
+import com.google.common.collect.Maps;
+import forge.game.ability.AbilityKey;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
+import forge.game.trigger.TriggerType;
+
+import java.util.List;
+import java.util.Map;
public class LifeExchangeEffect extends SpellAbilityEffect {
@@ -56,17 +60,27 @@ public class LifeExchangeEffect extends SpellAbilityEffect {
source.addRemembered(diff);
}
+ final Map lossMap = Maps.newHashMap();
if ((life1 > life2) && p1.canLoseLife() && p2.canGainLife()) {
final int diff = life1 - life2;
- p1.loseLife(diff, false, false);
+ final int lost = p1.loseLife(diff, false, false);
p2.gainLife(diff, source, sa);
+ if (lost > 0) {
+ lossMap.put(p1, lost);
+ }
} else if ((life2 > life1) && p2.canLoseLife() && p1.canGainLife()) {
final int diff = life2 - life1;
- p2.loseLife(diff, false, false);
+ final int lost = p2.loseLife(diff, false, false);
p1.gainLife(diff, source, sa);
+ if (lost > 0) {
+ lossMap.put(p2, lost);
+ }
} else {
- // they are equal, so nothing to do
+ // they are equal or can't be exchanged, so nothing to do
+ }
+ if (!lossMap.isEmpty()) { // Run triggers if any player actually lost life
+ final Map runParams = AbilityKey.mapFromPIMap(lossMap);
+ source.getGame().getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runParams, false);
}
}
-
}
diff --git a/forge-game/src/main/java/forge/game/ability/effects/LifeExchangeVariantEffect.java b/forge-game/src/main/java/forge/game/ability/effects/LifeExchangeVariantEffect.java
index c3d8c5359ca..0f4e75fb715 100644
--- a/forge-game/src/main/java/forge/game/ability/effects/LifeExchangeVariantEffect.java
+++ b/forge-game/src/main/java/forge/game/ability/effects/LifeExchangeVariantEffect.java
@@ -1,13 +1,17 @@
package forge.game.ability.effects;
-import java.util.List;
-
+import com.google.common.collect.Maps;
import forge.game.Game;
+import forge.game.ability.AbilityKey;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.event.GameEventCardStatsChanged;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
+import forge.game.trigger.TriggerType;
+
+import java.util.List;
+import java.util.Map;
public class LifeExchangeVariantEffect extends SpellAbilityEffect {
@@ -68,9 +72,16 @@ public class LifeExchangeVariantEffect extends SpellAbilityEffect {
if ((pLife > num) && p.canLoseLife()) {
final int diff = pLife - num;
- p.loseLife(diff, false, false);
+ final int lost = p.loseLife(diff, false, false);
source.addNewPT(power, toughness, timestamp, 0);
game.fireEvent(new GameEventCardStatsChanged(source));
+
+ if (lost > 0) { // Run triggers if player actually lost life
+ final Map lossMap = Maps.newHashMap();
+ lossMap.put(p, lost);
+ final Map runParams = AbilityKey.mapFromPIMap(lossMap);
+ source.getGame().getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runParams, false);
+ }
} else if ((num > pLife) && p.canGainLife()) {
final int diff = num - pLife;
p.gainLife(diff, source, sa);
diff --git a/forge-game/src/main/java/forge/game/ability/effects/LifeLoseEffect.java b/forge-game/src/main/java/forge/game/ability/effects/LifeLoseEffect.java
index a2afc3381ea..35bda39450a 100644
--- a/forge-game/src/main/java/forge/game/ability/effects/LifeLoseEffect.java
+++ b/forge-game/src/main/java/forge/game/ability/effects/LifeLoseEffect.java
@@ -1,12 +1,17 @@
package forge.game.ability.effects;
+import com.google.common.collect.Maps;
+import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
+import forge.game.trigger.TriggerType;
import forge.util.Lang;
import org.apache.commons.lang3.StringUtils;
+import java.util.Map;
+
public class LifeLoseEffect extends SpellAbilityEffect {
/* (non-Javadoc)
@@ -41,13 +46,23 @@ public class LifeLoseEffect extends SpellAbilityEffect {
final int lifeAmount = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("LifeAmount"), sa);
+ final Map lossMap = Maps.newHashMap();
for (final Player p : getTargetPlayers(sa)) {
if (!p.isInGame()) {
continue;
}
- lifeLost += p.loseLife(lifeAmount, false, false);
+ final int lost = p.loseLife(lifeAmount, false, false);
+ if (lost > 0) {
+ lossMap.put(p, lost);
+ }
+ lifeLost += lost;
}
sa.setSVar("AFLifeLost", "Number$" + lifeLost);
+
+ if (!lossMap.isEmpty()) { // Run triggers if any player actually lost life
+ final Map runParams = AbilityKey.mapFromPIMap(lossMap);
+ sa.getHostCard().getGame().getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runParams, false);
+ }
}
}
diff --git a/forge-game/src/main/java/forge/game/ability/effects/LifeSetEffect.java b/forge-game/src/main/java/forge/game/ability/effects/LifeSetEffect.java
index 82fbb2d2d44..f1b709fb688 100644
--- a/forge-game/src/main/java/forge/game/ability/effects/LifeSetEffect.java
+++ b/forge-game/src/main/java/forge/game/ability/effects/LifeSetEffect.java
@@ -1,16 +1,22 @@
package forge.game.ability.effects;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import forge.game.ability.AbilityKey;
+import forge.game.ability.AbilityUtils;
+import forge.game.ability.SpellAbilityEffect;
+import forge.game.card.Card;
+import forge.game.player.Player;
+import forge.game.player.PlayerCollection;
+import forge.game.player.PlayerController;
+import forge.game.spellability.SpellAbility;
+import forge.game.trigger.TriggerType;
+import forge.util.Lang;
+import forge.util.Localizer;
+
import java.util.ArrayList;
import java.util.List;
-
-import com.google.common.collect.Lists;
-
-import forge.game.ability.AbilityUtils;
-import forge.game.ability.SpellAbilityEffect;
-import forge.game.player.Player;
-import forge.game.player.PlayerCollection;
-import forge.game.spellability.SpellAbility;
-import forge.util.Localizer;
+import java.util.Map;
public class LifeSetEffect extends SpellAbilityEffect {
@@ -19,10 +25,38 @@ public class LifeSetEffect extends SpellAbilityEffect {
*/
@Override
public void resolve(SpellAbility sa) {
+ final Card source = sa.getHostCard();
final boolean redistribute = sa.hasParam("Redistribute");
- final int lifeAmount = redistribute ? 0 : AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("LifeAmount"), sa);
+ final int lifeAmount = redistribute ? 0 : AbilityUtils.calculateAmount(source, sa.getParam("LifeAmount"), sa);
final List lifetotals = new ArrayList<>();
- final PlayerCollection players = getTargetPlayers(sa);
+ final PlayerController pc = sa.getActivatingPlayer().getController();
+
+ PlayerCollection players = new PlayerCollection();
+ if (sa.hasParam("PlayerChoices")) {
+ PlayerCollection choices = AbilityUtils.getDefinedPlayers(source, sa.getParam("PlayerChoices"), sa);
+ int n = 1;
+ int min = 1;
+ if (sa.hasParam("ChoiceAmount")) {
+ if (sa.getParam("ChoiceAmount").equals("Any")) {
+ n = choices.size();
+ min = 0;
+ } else {
+ n = AbilityUtils.calculateAmount(source, sa.getParam("ChoiceAmount"), sa);
+ min = n;
+ }
+ }
+ final String prompt = sa.hasParam("ChoicePrompt") ? sa.getParam("ChoicePrompt") :
+ Localizer.getInstance().getMessage("lblChoosePlayer");
+ List chosen = pc.chooseEntitiesForEffect(choices, min, n, null, sa, prompt, null,
+ null);
+ players.addAll(chosen);
+ } else {
+ players = getTargetPlayers(sa);
+ }
+
+ if (players.isEmpty()) {
+ return;
+ }
if (redistribute) {
for (final Player p : players) {
@@ -33,23 +67,33 @@ public class LifeSetEffect extends SpellAbilityEffect {
}
}
+ final Map lossMap = Maps.newHashMap();
for (final Player p : players.threadSafeIterable()) {
if (!p.isInGame()) {
continue;
}
+ final int preLife = p.getLife();
if (!redistribute) {
p.setLife(lifeAmount, sa);
} else {
List validChoices = getDistribution(players, true, lifetotals);
- int life = sa.getActivatingPlayer().getController().chooseNumber(sa, Localizer.getInstance().getMessage("lblLifeTotal") + ": " + p, validChoices, p);
+ int life = pc.chooseNumber(sa, Localizer.getInstance().getMessage("lblLifeTotal") + ": " + p, validChoices, p);
p.setLife(life, sa);
lifetotals.remove((Integer) life);
players.remove(p);
}
+ final int diff = preLife - p.getLife();
+ if (diff > 0) {
+ lossMap.put(p, diff);
+ }
+ }
+ if (!lossMap.isEmpty()) { // Run triggers if any player actually lost life
+ final Map runParams = AbilityKey.mapFromPIMap(lossMap);
+ source.getGame().getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runParams, false);
}
}
- private static List getDistribution(PlayerCollection players, boolean top, List remainingChoices) {
+ private static List getDistribution(List players, boolean top, List remainingChoices) {
// distribution was successful
if (players.isEmpty()) {
// carry signal back
@@ -95,23 +139,18 @@ public class LifeSetEffect extends SpellAbilityEffect {
*/
@Override
protected String getStackDescription(SpellAbility sa) {
+ if (sa.hasParam("Redistribute")) {
+ if (sa.hasParam("SpellDescription")) {
+ return sa.getParam("SpellDescription");
+ } else {
+ return ("Please add StackDescription or SpellDescription for Redistribute in LifeSetEffect.");
+ }
+ }
final StringBuilder sb = new StringBuilder();
final int amount = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("LifeAmount"), sa);
- final boolean redistribute = sa.hasParam("Redistribute");
- List tgtPlayers = getTargetPlayers(sa);
- if (!redistribute) {
- for (final Player player : tgtPlayers) {
- sb.append(player).append(" ");
- }
- sb.append("life total becomes ").append(amount).append(".");
- } else {
- sb.append("Redistribute ");
- for (final Player player : tgtPlayers) {
- sb.append(player).append(" ");
- }
- sb.append("life totals.");
- }
+ sb.append(Lang.joinHomogenous(getTargetPlayers(sa)));
+ sb.append(" life total becomes ").append(amount).append(".");
return sb.toString();
}
diff --git a/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java
index d8d5153e2f3..25d8f308700 100644
--- a/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java
+++ b/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java
@@ -4,18 +4,21 @@ import java.util.*;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import forge.GameCommand;
import forge.card.CardType;
import forge.game.Game;
import forge.game.GameEntityCounterTable;
import forge.game.GameObject;
+import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.*;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
+import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.collect.FCollection;
@@ -81,9 +84,12 @@ public class RepeatEachEffect extends SpellAbilityEffect {
if (sa.hasParam("ChangeZoneTable")) {
sa.setChangeZoneTable(new CardZoneTable());
}
+ if (sa.hasParam("LoseLifeMap")) {
+ sa.setLoseLifeMap(Maps.newHashMap());
+ }
if (loopOverCards) {
- if (sa.hasParam("ChooseOrder") && repeatCards.size() >= 2) {
+ if (sa.hasParam("ChooseOrder") && repeatCards.size() > 1) {
final Player chooser = sa.getParam("ChooseOrder").equals("True") ? player :
AbilityUtils.getDefinedPlayers(source, sa.getParam("ChooseOrder"), sa).get(0);
repeatCards = chooser.getController().orderMoveToZoneList(repeatCards, ZoneType.None, sa);
@@ -207,5 +213,13 @@ public class RepeatEachEffect extends SpellAbilityEffect {
sa.getChangeZoneTable().triggerChangesZoneAll(game, sa);
sa.setChangeZoneTable(null);
}
+ if (sa.hasParam("LoseLifeMap")) {
+ Map lossMap = sa.getLoseLifeMap();
+ if (!lossMap.isEmpty()) {
+ final Map runParams2 = AbilityKey.mapFromPIMap(lossMap);
+ game.getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runParams2, false);
+ }
+ sa.setLoseLifeMap(null);
+ }
}
}
diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java
index 5d45f6ecfa4..f71a724b424 100644
--- a/forge-game/src/main/java/forge/game/card/CardFactory.java
+++ b/forge-game/src/main/java/forge/game/card/CardFactory.java
@@ -680,7 +680,7 @@ public class CardFactory {
List creatureTypes = null;
final CardCloneStates result = new CardCloneStates(in, sa);
- final String newName = sa.getParamOrDefault("NewName", null);
+ final String newName = sa.getParam("NewName");
ColorSet colors = null;
if (sa.hasParam("AddTypes")) {
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 b0e37ace58b..70a1796f0d7 100644
--- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java
+++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java
@@ -465,13 +465,21 @@ public class PhaseHandler implements java.io.Serializable {
throw new IllegalStateException("Phase.nextPhase() is called, but Stack isn't empty.");
}
+ final Map lossMap = Maps.newHashMap();
for (Player p : game.getPlayers()) {
int burn = p.getManaPool().clearPool(true).size();
if (p.getManaPool().hasBurn()) {
- p.loseLife(burn, false, true);
+ final int lost = p.loseLife(burn, false, true);
+ if (lost > 0) {
+ lossMap.put(p, lost);
+ }
}
}
+ if (!lossMap.isEmpty()) { // Run triggers if any player actually lost life
+ final Map runLifeLostParams = AbilityKey.mapFromPIMap(lossMap);
+ game.getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runLifeLostParams, false);
+ }
switch (phase) {
case UPKEEP:
diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java
index fbfe4c1a214..364a0ab174b 100644
--- a/forge-game/src/main/java/forge/game/player/Player.java
+++ b/forge-game/src/main/java/forge/game/player/Player.java
@@ -620,13 +620,26 @@ public class Player extends GameEntity implements Comparable {
return false;
}
- loseLife(lifePayment, false, false);
+ final int lost = loseLife(lifePayment, false, false);
cause.setPaidLife(lifePayment);
// Run triggers
final Map runParams = AbilityKey.mapFromPlayer(this);
runParams.put(AbilityKey.LifeAmount, lifePayment);
game.getTriggerHandler().runTrigger(TriggerType.PayLife, runParams, false);
+ if (lost > 0) { // Run triggers if player actually lost life
+ boolean runAll = false;
+ Map lossMap = cause.getLoseLifeMap();
+ if (lossMap == null) {
+ lossMap = Maps.newHashMap();
+ runAll = true;
+ }
+ lossMap.put(this, lost);
+ if (runAll) {
+ final Map runParams2 = AbilityKey.mapFromPIMap(lossMap);
+ game.getTriggerHandler().runTrigger(TriggerType.LifeLostAll, runParams2, false);
+ }
+ }
return true;
}
@@ -691,12 +704,7 @@ public class Player extends GameEntity implements Comparable {
}
else if (!hasKeyword("Damage doesn't cause you to lose life.")) {
// rule 118.2. Damage dealt to a player normally causes that player to lose that much life.
- if (isCombat) {
- // currently all abilities treat is as single event
- simultaneousDamage += amount;
- } else {
- loseLife(amount, true, false);
- }
+ simultaneousDamage += amount;
}
if (isCombat) {
@@ -829,9 +837,10 @@ public class Player extends GameEntity implements Comparable {
return restDamage;
}
- public final void dealCombatDamage() {
- loseLife(simultaneousDamage, true, false);
+ public final int processDamage() {
+ int lost = loseLife(simultaneousDamage, true, false);
simultaneousDamage = 0;
+ return lost;
}
/**
diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java
index 66ab466585d..f5f6bc63aa4 100644
--- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java
+++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java
@@ -186,6 +186,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
private CardDamageMap preventMap;
private GameEntityCounterTable counterTable;
private CardZoneTable changeZoneTable;
+ private Map loseLifeMap;
public CardCollection getLastStateBattlefield() {
return lastStateBattlefield;
@@ -2357,6 +2358,15 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
return null;
}
+ public Map getLoseLifeMap() {
+ if (loseLifeMap != null) {
+ return loseLifeMap;
+ } else if (getParent() != null) {
+ return getParent().getLoseLifeMap();
+ }
+ return null;
+ }
+
public void setDamageMap(final CardDamageMap map) {
damageMap = map;
}
@@ -2369,6 +2379,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
public void setChangeZoneTable(final CardZoneTable table) {
changeZoneTable = table;
}
+ public void setLoseLifeMap(final Map map) {
+ loseLifeMap = map;
+ }
public SpellAbility getOriginalAbility() {
return grantorOriginal;
diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerLifeLostAll.java b/forge-game/src/main/java/forge/game/trigger/TriggerLifeLostAll.java
new file mode 100644
index 00000000000..c64ab892e02
--- /dev/null
+++ b/forge-game/src/main/java/forge/game/trigger/TriggerLifeLostAll.java
@@ -0,0 +1,117 @@
+/*
+ * Forge: Play Magic: the Gathering.
+ * Copyright (C) 2011 Forge Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package forge.game.trigger;
+
+import com.google.common.collect.Maps;
+import forge.game.ability.AbilityKey;
+import forge.game.ability.AbilityUtils;
+import forge.game.card.Card;
+import forge.game.player.Player;
+import forge.game.spellability.SpellAbility;
+import forge.util.Expressions;
+
+import java.util.Map;
+
+/**
+ *
+ * Trigger_LifeLostAll class.
+ *
+ *
+ * 4/27/2023 - this trigger is written for only Ob Nixilis, Captive Kingpin – any future uses will probably need
+ * additional logic
+ *
+ * @author Forge (Northmoc)
+ * @version $Id$
+ */
+public class TriggerLifeLostAll extends Trigger {
+
+ /**
+ *
+ * Constructor for Trigger_LifeLost.
+ *
+ *
+ * @param params
+ * a {@link java.util.HashMap} object.
+ * @param host
+ * a {@link forge.game.card.Card} object.
+ * @param intrinsic
+ * the intrinsic
+ */
+ public TriggerLifeLostAll(final Map params, final Card host, final boolean intrinsic) {
+ super(params, host, intrinsic);
+ }
+
+ /** {@inheritDoc}
+ * @param runParams*/
+ @Override
+ public final boolean performTest(final Map runParams) {
+ final Map testMap = filteredMap((Map) runParams.get(AbilityKey.Map));
+ if (testMap.isEmpty()) {
+ return false;
+ }
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final void setTriggeringObjects(final SpellAbility sa, Map runParams) {
+ final Map map = (Map) runParams.get(AbilityKey.Map);
+
+ sa.setTriggeringObject(AbilityKey.Map, filteredMap(map));
+ sa.setTriggeringObject(AbilityKey.Player, map.keySet());
+ }
+
+ @Override
+ public String getImportantStackObjects(SpellAbility sa) {
+ StringBuilder sb = new StringBuilder();
+ final Map map = (Map) sa.getTriggeringObject(AbilityKey.Map);
+ int n = 0;
+ for (final Map.Entry e : map.entrySet()) {
+ sb.append(e.getKey()).append(": ").append(e.getValue());
+ n++;
+ if (map.size() > n) {
+ sb.append(", ");
+ }
+ }
+ return sb.toString();
+ }
+
+ private Map filteredMap(Map map) {
+ Map passMap = Maps.newHashMap();
+ if (hasParam("ValidPlayer")) {
+ for (final Map.Entry e : map.entrySet()) {
+ if (matchesValidParam("ValidPlayer", e.getKey())) {
+ passMap.put(e.getKey(), e.getValue());
+ }
+ }
+ if (passMap.isEmpty()) {
+ return passMap;
+ }
+ }
+ if (hasParam("ValidAmountEach")) {
+ final String comp = getParam("ValidAmountEach");
+ final int value = AbilityUtils.calculateAmount(getHostCard(), comp.substring(2), this);
+ for (final Map.Entry e : passMap.entrySet()) {
+ if (!Expressions.compare(e.getValue(), comp.substring(0, 2), value)) {
+ return Maps.newHashMap();
+ }
+ }
+ }
+ return passMap;
+ }
+}
diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerType.java b/forge-game/src/main/java/forge/game/trigger/TriggerType.java
index 990af336a5b..90b6f1f21e6 100644
--- a/forge-game/src/main/java/forge/game/trigger/TriggerType.java
+++ b/forge-game/src/main/java/forge/game/trigger/TriggerType.java
@@ -83,6 +83,7 @@ public enum TriggerType {
LandPlayed(TriggerLandPlayed.class),
LifeGained(TriggerLifeGained.class),
LifeLost(TriggerLifeLost.class),
+ LifeLostAll(TriggerLifeLostAll.class),
LosesGame(TriggerLosesGame.class),
ManaAdded(TriggerManaAdded.class),
MilledAll(TriggerMilledAll.class),
diff --git a/forge-gui/res/cardsfolder/f/forge_devil.txt b/forge-gui/res/cardsfolder/f/forge_devil.txt
index b7b7cdcbce5..27ffd445a94 100644
--- a/forge-gui/res/cardsfolder/f/forge_devil.txt
+++ b/forge-gui/res/cardsfolder/f/forge_devil.txt
@@ -3,6 +3,7 @@ ManaCost:R
Types:Creature Devil
PT:1/1
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDealDamage | TriggerDescription$ When CARDNAME enters the battlefield, it deals 1 damage to target creature and 1 damage to you.
-SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 1 | SubAbility$ DBDamageYou
-SVar:DBDamageYou:DB$ DealDamage | Defined$ You | NumDmg$ 1
+SVar:TrigDealDamage:DB$ DealDamage | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 1 | DamageMap$ True | SubAbility$ DBDamageYou
+SVar:DBDamageYou:DB$ DealDamage | Defined$ You | NumDmg$ 1 | SubAbility$ DBDamageResolve
+SVar:DBDamageResolve:DB$ DamageResolve
Oracle:When Forge Devil enters the battlefield, it deals 1 damage to target creature and 1 damage to you.
diff --git a/forge-gui/res/cardsfolder/h/hordewing_skaab.txt b/forge-gui/res/cardsfolder/h/hordewing_skaab.txt
index e1e46e616b8..60827464684 100644
--- a/forge-gui/res/cardsfolder/h/hordewing_skaab.txt
+++ b/forge-gui/res/cardsfolder/h/hordewing_skaab.txt
@@ -4,7 +4,7 @@ Types:Creature Zombie Horror
PT:3/3
K:Flying
S:Mode$ Continuous | Affected$ Zombie.YouCtrl+Other | AddKeyword$ Flying | Description$ Other Zombies you control have flying.
-T:Mode$ DamageAll | ValidSource$ Creature.Zombie+YouCtrl | ValidTarget$ Player.Opponent | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ TrigDraw | OptionalDecider$ You | TriggerDescription$ Whenever one or more Zombies you control deal combat damage to one or more of your opponents, you may draw cards equal to the number of opponents dealt damage this way. If you do, discard that many cards.
+T:Mode$ DamageAll | ValidSource$ Creature.Zombie+YouCtrl | ValidTarget$ Opponent | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ TrigDraw | OptionalDecider$ You | TriggerDescription$ Whenever one or more Zombies you control deal combat damage to one or more of your opponents, you may draw cards equal to the number of opponents dealt damage this way. If you do, discard that many cards.
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ X | RememberDrawn$ True | SubAbility$ DBDiscard
SVar:DBDiscard:DB$ Discard | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GEX | Defined$ You | Mode$ TgtChoose | NumCards$ X | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
diff --git a/forge-gui/res/cardsfolder/k/killing_wave.txt b/forge-gui/res/cardsfolder/k/killing_wave.txt
index 186baae64c8..821496674f5 100644
--- a/forge-gui/res/cardsfolder/k/killing_wave.txt
+++ b/forge-gui/res/cardsfolder/k/killing_wave.txt
@@ -1,8 +1,14 @@
Name:Killing Wave
ManaCost:X B
Types:Sorcery
-A:SP$ RepeatEach | Cost$ X B | RepeatCards$ Creature | Zone$ Battlefield | RepeatSubAbility$ DBSacUnless | SpellDescription$ For each creature, its controller sacrifices it unless they pay X life.
-SVar:DBSacUnless:DB$ Sacrifice | Defined$ Player | SacValid$ Remembered.Self | UnlessCost$ PayLife | UnlessPayer$ RememberedController | Random$ True | StackDescription$ Sacrifice {c:Remembered}
+A:SP$ RepeatEach | Cost$ X B | RepeatPlayers$ Player | RepeatSubAbility$ DBChooseKeep | SubAbility$ DBRepeatPay | SpellDescription$ For each creature, its controller sacrifices it unless they pay X life.
+SVar:DBChooseKeep:DB$ ChooseCard | Defined$ Remembered | Choices$ Creature.RememberedPlayerCtrl | MinAmount$ 0 | Amount$ Count$Valid Creature.RememberedPlayerCtrl | RememberChosen$ True
+SVar:DBRepeatPay:DB$ RepeatEach | RepeatPlayers$ Player | LoseLifeMap$ True | RepeatSubAbility$ DBPay | SubAbility$ DBSacAll
+SVar:DBPay:DB$ Pump | ForgetObjects$ Valid Creature.RememberedPlayerCtrl | UnlessCost$ PayLife | UnlessPayer$ Remembered
+SVar:DBSacAll:DB$ SacrificeAll | ValidCards$ Creature.IsNotRemembered | SubAbility$ DBCleanup
+SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$xPaid
+SVar:Y:SVar$X/Times.Z
+SVar:Z:Count$Valid Creature.RememberedPlayerCtrl+IsRemembered
AI:RemoveDeck:All
Oracle:For each creature, its controller sacrifices it unless they pay X life.
diff --git a/forge-gui/res/cardsfolder/n/night_market_lookout.txt b/forge-gui/res/cardsfolder/n/night_market_lookout.txt
index b2249ee56ce..2bf23350964 100644
--- a/forge-gui/res/cardsfolder/n/night_market_lookout.txt
+++ b/forge-gui/res/cardsfolder/n/night_market_lookout.txt
@@ -3,7 +3,7 @@ ManaCost:B
Types:Creature Human Rogue
PT:1/1
T:Mode$ Taps | ValidCard$ Card.Self | Execute$ TrigDrain | TriggerDescription$ Whenever CARDNAME becomes tapped, each opponent loses 1 life and you gain 1 life.
-SVar:TrigDrain:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 1 | SubAbility$ DBGainLife
+SVar:TrigDrain:DB$ LoseLife | Defined$ Opponent | LifeAmount$ 1 | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1
DeckHas:Ability$LifeGain
Oracle:Whenever Night Market Lookout becomes tapped, each opponent loses 1 life and you gain 1 life.
diff --git a/forge-gui/res/cardsfolder/r/reverse_the_sands.txt b/forge-gui/res/cardsfolder/r/reverse_the_sands.txt
index 6cfd02348d2..5c26624107a 100644
--- a/forge-gui/res/cardsfolder/r/reverse_the_sands.txt
+++ b/forge-gui/res/cardsfolder/r/reverse_the_sands.txt
@@ -1,6 +1,6 @@
Name:Reverse the Sands
ManaCost:6 W W
Types:Sorcery
-A:SP$ SetLife | Cost$ 6 W W | Defined$ Player | Redistribute$ True | SpellDescription$ Redistribute any number of players' life totals. (Each of those players gets one life total back.)
+A:SP$ SetLife | PlayerChoices$ Player | ChoiceAmount$ Any | ChoicePrompt$ Choose any number of players | Redistribute$ True | SpellDescription$ Redistribute any number of players' life totals. (Each of those players gets one life total back.)
AI:RemoveDeck:All
Oracle:Redistribute any number of players' life totals. (Each of those players gets one life total back.)
diff --git a/forge-gui/res/cardsfolder/t/tree_of_perdition.txt b/forge-gui/res/cardsfolder/t/tree_of_perdition.txt
index e926314637f..58f28ca5ba7 100644
--- a/forge-gui/res/cardsfolder/t/tree_of_perdition.txt
+++ b/forge-gui/res/cardsfolder/t/tree_of_perdition.txt
@@ -3,5 +3,5 @@ ManaCost:3 B
Types:Creature Plant
PT:0/13
K:Defender
-A:AB$ ExchangeLifeVariant | Cost$ T | ConditionPresent$ Creature.StrictlySelf | ValidTgts$ Opponent | Mode$ Toughness | SpellDescription$ Exchange target opponent's life total with CARDNAME's toughness. | StackDescription$ SpellDescription
+A:AB$ ExchangeLifeVariant | Cost$ T | ConditionPresent$ Creature.StrictlySelf | ValidTgts$ Opponent | Mode$ Toughness | SpellDescription$ Exchange target opponent's life total with CARDNAME's toughness. | StackDescription$ REP target opponent_{p:Targeted}
Oracle:Defender\n{T}: Exchange target opponent's life total with Tree of Perdition's toughness.
diff --git a/forge-gui/res/cardsfolder/upcoming/ob_nixilis_captive_kingpin.txt b/forge-gui/res/cardsfolder/upcoming/ob_nixilis_captive_kingpin.txt
new file mode 100644
index 00000000000..9b92838686a
--- /dev/null
+++ b/forge-gui/res/cardsfolder/upcoming/ob_nixilis_captive_kingpin.txt
@@ -0,0 +1,14 @@
+Name:Ob Nixilis, Captive Kingpin
+ManaCost:2 B R
+Types:Legendary Creature Demon
+PT:4/3
+KFlying
+K:Trample
+T:Mode$ LifeLostAll | ValidPlayer$ Opponent | ValidAmountEach$ EQ1 | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Whenever one or more opponents each lose exactly 1 life, put a +1/+1 counter on CARDNAME. Exile the top card of your library. Until your next end step, you may play that card.
+SVar:TrigPutCounter:DB$ PutCounter | CounterType$ P1P1 | SubAbility$ DBExileTop
+SVar:DBExileTop:DB$ Dig | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True | SubAbility$ DBEffect
+SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | RememberObjects$ Remembered | Duration$ UntilYourNextEndStep | SubAbility$ DBCleanup | ForgetOnMoved$ Exile
+SVar:STPlay:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ Until your next end step, you may play that card.
+SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+DeckHas:Ability$Counters
+Oracle:Flying, trample\nWhenever one or more opponents each lose exactly 1 life, put a +1/+1 counter on Ob Nixilis, Captive Kingpin. Exile the top card of your library. Until your next end step, you may play that card.
From dbd730bee15aa755d04b55ac8ec5de36218ced33 Mon Sep 17 00:00:00 2001
From: tool4EvEr
Date: Mon, 17 Jul 2023 10:18:06 +0200
Subject: [PATCH 5/7] Fix Kamiz script failing calls to WrappedAbility
---
.../forge/game/spellability/SpellAbility.java | 22 ++++++++-----------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java
index 66ab466585d..6f0ac7aaeab 100644
--- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java
+++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java
@@ -66,7 +66,6 @@ import forge.game.staticability.StaticAbilityCastWithFlash;
import forge.game.staticability.StaticAbilityMustTarget;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerType;
-import forge.game.trigger.WrappedAbility;
import forge.game.zone.ZoneType;
import forge.util.Aggregates;
import forge.util.CardTranslation;
@@ -1843,14 +1842,14 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
*/
public CardCollectionView findTargetedCards() {
// First search for targeted cards associated with current ability
- if (targetChosen.isTargetingAnyCard()) {
- return targetChosen.getTargetCards();
+ if (getTargets().isTargetingAnyCard()) {
+ return getTargets().getTargetCards();
}
// Next search for source cards of targeted SAs associated with current ability
- if (targetChosen.isTargetingAnySpell()) {
+ if (getTargets().isTargetingAnySpell()) {
CardCollection res = new CardCollection();
- for (final SpellAbility ability : targetChosen.getTargetSpells()) {
+ for (final SpellAbility ability : getTargets().getTargetSpells()) {
res.add(ability.getHostCard());
}
return res;
@@ -1872,16 +1871,13 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
}
public SpellAbility getSATargetingCard() {
- return targetChosen.isTargetingAnyCard() ? this : getParentTargetingCard();
+ return getTargets().isTargetingAnyCard() ? this : getParentTargetingCard();
}
public SpellAbility getParentTargetingCard() {
SpellAbility parent = getParent();
- if (parent instanceof WrappedAbility) {
- parent = ((WrappedAbility) parent).getWrappedAbility();
- }
while (parent != null) {
- if (parent.targetChosen.isTargetingAnyCard()) {
+ if (parent.getTargets().isTargetingAnyCard()) {
return parent;
}
parent = parent.getParent();
@@ -1890,13 +1886,13 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
}
public SpellAbility getSATargetingSA() {
- return targetChosen.isTargetingAnySpell() ? this : getParentTargetingSA();
+ return getTargets().isTargetingAnySpell() ? this : getParentTargetingSA();
}
public SpellAbility getParentTargetingSA() {
SpellAbility parent = getParent();
while (parent != null) {
- if (parent.targetChosen.isTargetingAnySpell())
+ if (parent.getTargets().isTargetingAnySpell())
return parent;
parent = parent.getParent();
}
@@ -1904,7 +1900,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
}
public SpellAbility getSATargetingPlayer() {
- return targetChosen.isTargetingAnyPlayer() ? this : getParentTargetingPlayer();
+ return getTargets().isTargetingAnyPlayer() ? this : getParentTargetingPlayer();
}
public SpellAbility getParentTargetingPlayer() {
From 2b5a7f09c91ac31ced479fc9df12458e680314ea Mon Sep 17 00:00:00 2001
From: tool4EvEr
Date: Mon, 17 Jul 2023 11:01:37 +0200
Subject: [PATCH 6/7] Clean up
---
.../forge/game/ability/effects/ChooseCardEffect.java | 4 +---
.../main/java/forge/game/replacement/ReplaceToken.java | 6 ------
forge-gui/res/cardsfolder/a/anathemancer.txt | 5 ++---
.../res/cardsfolder/a/aurelia_exemplar_of_justice.txt | 7 +++----
forge-gui/res/cardsfolder/e/echoing_courage.txt | 5 ++---
forge-gui/res/cardsfolder/e/echoing_decay.txt | 5 ++---
forge-gui/res/cardsfolder/e/elvish_healer.txt | 5 ++---
forge-gui/res/cardsfolder/f/fatal_lore.txt | 2 +-
forge-gui/res/cardsfolder/i/ill_gotten_gains.txt | 5 ++---
forge-gui/res/cardsfolder/i/intellect_devourer.txt | 8 ++------
forge-gui/res/cardsfolder/i/intet_the_dreamer.txt | 10 +++-------
forge-gui/res/cardsfolder/i/intimidation_bolt.txt | 5 ++---
forge-gui/res/cardsfolder/m/mindclaw_shaman.txt | 5 ++---
forge-gui/res/cardsfolder/n/nightveil_specter.txt | 8 ++------
.../res/cardsfolder/n/nissa_steward_of_elements.txt | 5 ++---
.../n/nissa_vastwood_seer_nissa_sage_animist.txt | 7 +++----
forge-gui/res/cardsfolder/t/the_ruinous_powers.txt | 2 +-
forge-gui/res/cardsfolder/t/theater_of_horrors.txt | 8 ++------
.../res/cardsfolder/upcoming/fires_of_mount_doom.txt | 4 ++--
forge-gui/res/cardsfolder/w/waking_the_trolls.txt | 7 +++----
forge-gui/res/cardsfolder/w/winnow.txt | 7 +++----
forge-gui/res/cardsfolder/x/xira_the_golden_sting.txt | 2 +-
22 files changed, 43 insertions(+), 79 deletions(-)
diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java
index c40b0273535..87719ec938b 100644
--- a/forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java
+++ b/forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java
@@ -125,9 +125,7 @@ public class ChooseCardEffect extends SpellAbilityEffect {
for (final String type : partyTypes) {
CardCollection valids = CardLists.filter(p.getCardsIn(ZoneType.Battlefield),
CardPredicates.isType(type));
- for (Card alreadyChosen : chosen) {
- valids.remove(alreadyChosen);
- }
+ valids.removeAll(chosen);
if (!valids.isEmpty()) {
final String prompt = Localizer.getInstance().getMessage("lblChoose") + " " +
Lang.nounWithNumeralExceptOne(1, type);
diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceToken.java b/forge-game/src/main/java/forge/game/replacement/ReplaceToken.java
index 2b40be93cfc..0a4371621ee 100644
--- a/forge-game/src/main/java/forge/game/replacement/ReplaceToken.java
+++ b/forge-game/src/main/java/forge/game/replacement/ReplaceToken.java
@@ -39,12 +39,6 @@ public class ReplaceToken extends ReplacementEffect {
return false;
}
- /*/
- if (!matchesValidParam("ValidToken", runParams.get(AbilityKey.Token))) {
- return false;
- }
- //*/
-
if (filterAmount((TokenCreateTable) runParams.get(AbilityKey.Token)) <= 0) {
return false;
}
diff --git a/forge-gui/res/cardsfolder/a/anathemancer.txt b/forge-gui/res/cardsfolder/a/anathemancer.txt
index 8dbd98abf0a..214e982028e 100644
--- a/forge-gui/res/cardsfolder/a/anathemancer.txt
+++ b/forge-gui/res/cardsfolder/a/anathemancer.txt
@@ -4,7 +4,6 @@ Types:Creature Zombie Wizard
PT:2/2
K:Unearth:5 B R
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDamage | TriggerDescription$ When CARDNAME enters the battlefield, it deals damage to target player equal to the number of nonbasic lands that player controls.
-SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Player | TgtPrompt$ Select target player | NumDmg$ X | RememberTargets$ True | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
-SVar:X:Count$Valid Land.nonBasic+RememberedPlayerCtrl
+SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Player | TgtPrompt$ Select target player | NumDmg$ X
+SVar:X:Count$Valid Land.nonBasic+TargetedPlayerCtrl
Oracle:When Anathemancer enters the battlefield, it deals damage to target player equal to the number of nonbasic lands that player controls.\nUnearth {5}{B}{R} ({5}{B}{R}: Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a sorcery.)
diff --git a/forge-gui/res/cardsfolder/a/aurelia_exemplar_of_justice.txt b/forge-gui/res/cardsfolder/a/aurelia_exemplar_of_justice.txt
index 619c0c388b8..79517835716 100644
--- a/forge-gui/res/cardsfolder/a/aurelia_exemplar_of_justice.txt
+++ b/forge-gui/res/cardsfolder/a/aurelia_exemplar_of_justice.txt
@@ -5,9 +5,8 @@ PT:2/5
K:Flying
K:Mentor
T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ DBPump | TriggerDescription$ At the beginning of combat on your turn, choose up to one target creature you control. Until end of turn, that creature gets +2/+0, gains trample if it's red, and gains vigilance if it's white.
-SVar:DBPump:DB$ Pump | ValidTgts$ Creature.YouCtrl | NumAtt$ 2 | RememberTargets$ True | SubAbility$ DBPump1
-SVar:DBPump1:DB$ Pump | Defined$ Remembered | KW$ Trample | ConditionDefined$ Remembered | ConditionPresent$ Card.Red | SubAbility$ DBPump2
-SVar:DBPump2:DB$ Pump | Defined$ Remembered | KW$ Vigilance | ConditionDefined$ Remembered | ConditionPresent$ Card.White | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+SVar:DBPump:DB$ Pump | ValidTgts$ Creature.YouCtrl | NumAtt$ 2 | SubAbility$ DBPump1
+SVar:DBPump1:DB$ Pump | Defined$ Targeted | KW$ Trample | ConditionDefined$ Targeted | ConditionPresent$ Card.Red | SubAbility$ DBPump2
+SVar:DBPump2:DB$ Pump | Defined$ Targeted | KW$ Vigilance | ConditionDefined$ Targeted | ConditionPresent$ Card.White
DeckHas:Ability$Counters
Oracle:Flying\nMentor (Whenever this creature attacks, put a +1/+1 counter on target attacking creature with lesser power.)\nAt the beginning of combat on your turn, choose up to one target creature you control. Until end of turn, that creature gets +2/+0, gains trample if it's red, and gains vigilance if it's white.
diff --git a/forge-gui/res/cardsfolder/e/echoing_courage.txt b/forge-gui/res/cardsfolder/e/echoing_courage.txt
index 85f57facf19..09cf537a493 100644
--- a/forge-gui/res/cardsfolder/e/echoing_courage.txt
+++ b/forge-gui/res/cardsfolder/e/echoing_courage.txt
@@ -1,7 +1,6 @@
Name:Echoing Courage
ManaCost:1 G
Types:Instant
-A:SP$ Pump | Cost$ 1 G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +2 | NumDef$ +2 | SubAbility$ DBPumpAll | RememberTargets$ True | ForgetOtherTargets$ True | SpellDescription$ Target creature and all other creatures with the same name as that creature get +2/+2 until end of turn.
-SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Remembered.Creature+Other+sameName | NumAtt$ +2 | NumDef$ +2 | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+A:SP$ Pump | Cost$ 1 G | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ +2 | NumDef$ +2 | SubAbility$ DBPumpAll | SpellDescription$ Target creature and all other creatures with the same name as that creature get +2/+2 until end of turn.
+SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Targeted.Creature+Other+sameName | NumAtt$ +2 | NumDef$ +2
Oracle:Target creature and all other creatures with the same name as that creature get +2/+2 until end of turn.
diff --git a/forge-gui/res/cardsfolder/e/echoing_decay.txt b/forge-gui/res/cardsfolder/e/echoing_decay.txt
index adbc2125a50..1f89a20abf3 100644
--- a/forge-gui/res/cardsfolder/e/echoing_decay.txt
+++ b/forge-gui/res/cardsfolder/e/echoing_decay.txt
@@ -1,8 +1,7 @@
Name:Echoing Decay
ManaCost:1 B
Types:Instant
-A:SP$ Pump | Cost$ 1 B | ValidTgts$ Creature | TgtPrompt$ Select target creature | RememberTargets$ True | NumAtt$ -2 | NumDef$ -2 | SubAbility$ DBPumpAll | SpellDescription$ Target creature and all other creatures with the same name as that creature get -2/-2 until end of turn.
-SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Remembered.sameName+Other | NumAtt$ -2 | NumDef$ -2 | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+A:SP$ Pump | Cost$ 1 B | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumAtt$ -2 | NumDef$ -2 | SubAbility$ DBPumpAll | SpellDescription$ Target creature and all other creatures with the same name as that creature get -2/-2 until end of turn.
+SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Targeted.sameName+Other | NumAtt$ -2 | NumDef$ -2
AI:RemoveDeck:All
Oracle:Target creature and all other creatures with the same name as that creature get -2/-2 until end of turn.
diff --git a/forge-gui/res/cardsfolder/e/elvish_healer.txt b/forge-gui/res/cardsfolder/e/elvish_healer.txt
index b173d1617ce..eab2b928057 100644
--- a/forge-gui/res/cardsfolder/e/elvish_healer.txt
+++ b/forge-gui/res/cardsfolder/e/elvish_healer.txt
@@ -2,9 +2,8 @@ Name:Elvish Healer
ManaCost:2 W
Types:Creature Elf Cleric
PT:1/2
-A:AB$ PreventDamage | Cost$ T | ValidTgts$ Any | Amount$ X | RememberTargets$ True | SubAbility$ DBCleanup | SpellDescription$ Prevent the next 1 damage that would be dealt to any target this turn. If it's a green creature, prevent the next 2 damage instead.
-SVar:X:Remembered$Valid Creature.Green/Plus.1
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+A:AB$ PreventDamage | Cost$ T | ValidTgts$ Any | Amount$ X | SpellDescription$ Prevent the next 1 damage that would be dealt to any target this turn. If it's a green creature, prevent the next 2 damage instead.
+SVar:X:Targeted$Valid Creature.Green/Plus.1
AI:RemoveDeck:Random
DeckHints:Color$Green
Oracle:{T}: Prevent the next 1 damage that would be dealt to any target this turn. If it's a green creature, prevent the next 2 damage instead.
diff --git a/forge-gui/res/cardsfolder/f/fatal_lore.txt b/forge-gui/res/cardsfolder/f/fatal_lore.txt
index 0260db54ff6..fd86a53e4d7 100644
--- a/forge-gui/res/cardsfolder/f/fatal_lore.txt
+++ b/forge-gui/res/cardsfolder/f/fatal_lore.txt
@@ -4,6 +4,6 @@ Types:Sorcery
A:SP$ Charm | Cost$ 2 B B | Chooser$ Opponent | Choices$ DrawThree,DestroyAndDraw
SVar:DrawThree:DB$ Draw | NumCards$ 3 | Defined$ You | SpellDescription$ You draw three cards.
SVar:DestroyAndDraw:DB$ Destroy | ValidTgts$ Creature.ChosenCtrl | TgtPrompt$ Select target creature | TargetMin$ 0 | TargetMax$ 2 | NoRegen$ True | SpellDescription$ You destroy up to two target creatures that opponent controls and that player draws up to three cards. Those creatures can't be regenerated. | SubAbility$ ChooserDraws
-SVar:ChooserDraws:DB$ Draw | NumCards$ 3 | Defined$ ChosenPlayer
+SVar:ChooserDraws:DB$ Draw | NumCards$ 3 | Defined$ ChosenPlayer | UpTo$ True
AI:RemoveDeck:All
Oracle:An opponent chooses one —\n• You draw three cards.\n• You destroy up to two target creatures that player controls. They can't be regenerated. That player draws up to three cards.
diff --git a/forge-gui/res/cardsfolder/i/ill_gotten_gains.txt b/forge-gui/res/cardsfolder/i/ill_gotten_gains.txt
index 152f9807407..a20f5a87514 100644
--- a/forge-gui/res/cardsfolder/i/ill_gotten_gains.txt
+++ b/forge-gui/res/cardsfolder/i/ill_gotten_gains.txt
@@ -2,8 +2,7 @@ Name:Ill-Gotten Gains
ManaCost:2 B B
Types:Sorcery
A:SP$ Discard | Cost$ 2 B B | Mode$ Hand | Defined$ Player | SubAbility$ DBExile | SpellDescription$ Exile CARDNAME. Each player discards their hand, then returns up to three cards from their graveyard to their hand.
-SVar:DBExile:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | SubAbility$ DBChangeZoneChoose
-SVar:DBChangeZoneChoose:DB$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ DBChangeZone
-SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | ChangeNum$ 3 | ChangeType$ Card | DefinedPlayer$ Remembered | Hidden$ True
+SVar:DBExile:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | SubAbility$ DBChangeZone
+SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | ChangeNum$ 3 | ChangeType$ Card | DefinedPlayer$ Player | Hidden$ True
AI:RemoveDeck:All
Oracle:Exile Ill-Gotten Gains. Each player discards their hand, then returns up to three cards from their graveyard to their hand.
diff --git a/forge-gui/res/cardsfolder/i/intellect_devourer.txt b/forge-gui/res/cardsfolder/i/intellect_devourer.txt
index 05e70cfb4e5..497559e7740 100644
--- a/forge-gui/res/cardsfolder/i/intellect_devourer.txt
+++ b/forge-gui/res/cardsfolder/i/intellect_devourer.txt
@@ -3,10 +3,6 @@ ManaCost:3 B
Types:Creature Horror
PT:2/4
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ Devour Intellect — When CARDNAME enters the battlefield, each opponent exiles a card from their hand until CARDNAME leaves the battlefield.
-SVar:TrigExile:DB$ ChangeZone | Origin$ Hand | Destination$ Exile | ChangeType$ Card | DefinedPlayer$ Opponent | Mandatory$ True | ChangeType$ Card | Hidden$ True | Duration$ UntilHostLeavesPlay | IsCurse$ True | RememberChanged$ True
-S:Mode$ Continuous | MayPlay$ True | MayPlayIgnoreColor$ True | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ Body Thief — You may play lands and cast spells from among cards exiled with CARDNAME. If you cast a spell this way, you may spend mana as though it were mana of any color to cast it.
-T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBForget
-SVar:DBForget:DB$ Pump | ForgetObjects$ TriggeredCard
-T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | Static$ True | ValidCard$ Card.Self | Execute$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+SVar:TrigExile:DB$ ChangeZone | Origin$ Hand | Destination$ Exile | ChangeType$ Card | DefinedPlayer$ Opponent | Mandatory$ True | ChangeType$ Card | Hidden$ True | Duration$ UntilHostLeavesPlay | IsCurse$ True
+S:Mode$ Continuous | MayPlay$ True | MayPlayIgnoreColor$ True | Affected$ Card.ExiledWithSource | AffectedZone$ Exile | Description$ Body Thief — You may play lands and cast spells from among cards exiled with CARDNAME. If you cast a spell this way, you may spend mana as though it were mana of any color to cast it.
Oracle:Devour Intellect — When Intellect Devourer enters the battlefield, each opponent exiles a card from their hand until Intellect Devourer leaves the battlefield.\nBody Thief — You may play lands and cast spells from among cards exiled with Intellect Devourer. If you cast a spell this way, you may spend mana as though it were mana of any color to cast it.
diff --git a/forge-gui/res/cardsfolder/i/intet_the_dreamer.txt b/forge-gui/res/cardsfolder/i/intet_the_dreamer.txt
index 67b1ba92009..9e00adea7cd 100644
--- a/forge-gui/res/cardsfolder/i/intet_the_dreamer.txt
+++ b/forge-gui/res/cardsfolder/i/intet_the_dreamer.txt
@@ -3,15 +3,11 @@ ManaCost:3 U R G
Types:Legendary Creature Dragon
PT:6/6
K:Flying
-T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | OptionalDecider$ You | Execute$ TrigExile | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, you may pay {2}{U}. If you do, exile the top card of your library face down. You may look at that card for as long as it remains exiled. You may play that card without paying its mana cost for as long as CARDNAME remains on the battlefield.
+T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | OptionalDecider$ You | Execute$ TrigExile | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, you may pay {2}{U}. If you do, exile the top card of your library face down. You may look at that card for as long as it remains exiled. You may play that card without paying its mana cost for as long as NICKNAME remains on the battlefield.
SVar:TrigExile:AB$ ChangeZone | Cost$ 2 U | Defined$ TopOfLibrary | Origin$ Library | Destination$ Exile | ExileFaceDown$ True | RememberChanged$ True | SubAbility$ DBEffect
-SVar:DBEffect:DB$ Effect | RememberObjects$ Remembered | StaticAbilities$ STMayLookAt | Triggers$ LeavesExile | Duration$ Permanent | SubAbility$ DBEffect2
+SVar:DBEffect:DB$ Effect | RememberObjects$ Remembered | StaticAbilities$ STMayLookAt | ForgetOnMoved$ Exile | Duration$ Permanent | SubAbility$ DBEffect2
SVar:STMayLookAt:Mode$ Continuous | EffectZone$ Command | Affected$ Card.IsRemembered | MayLookAt$ You | AffectedZone$ Exile | Description$ You may look at that card for as long as it remains exiled.
-SVar:LeavesExile:Mode$ ChangesZone | TriggerZones$ Command | Origin$ Exile | Destination$ Any | ValidCard$ Card.IsRemembered | Static$ True | Execute$ ExileSelf
-SVar:ExileSelf:DB$ ChangeZone | Origin$ Command | Destination$ Exile
-SVar:DBEffect2:DB$ Effect | Name$ Intet, the Dreamer Effect | StaticAbilities$ STMayPlay | Triggers$ PlayedExiled,ExiledLandPlayed | RememberObjects$ Remembered | Duration$ UntilHostLeavesPlay | SubAbility$ DBCleanup
+SVar:DBEffect2:DB$ Effect | Name$ Intet, the Dreamer Effect | StaticAbilities$ STMayPlay | ForgetOnMoved$ Exile | RememberObjects$ Remembered | Duration$ UntilHostLeavesPlay | SubAbility$ DBCleanup
SVar:STMayPlay:Mode$ Continuous | EffectZone$ Command | Affected$ Card.IsRemembered | MayPlay$ True | MayPlayWithoutManaCost$ True | AffectedZone$ Exile | Description$ You may play that card without paying its mana cost for as long as Intet remains on the battlefield.
-SVar:PlayedExiled:Mode$ SpellCast | TriggerZones$ Command | ValidCard$ Card.IsRemembered | Static$ True | Execute$ ExileSelf
-SVar:ExiledLandPlayed:Mode$ LandPlayed | TriggerZones$ Command | ValidCard$ Card.IsRemembered | Static$ True | Execute$ ExileSelf
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
Oracle:Flying\nWhenever Intet, the Dreamer deals combat damage to a player, you may pay {2}{U}. If you do, exile the top card of your library face down. You may look at that card for as long as it remains exiled. You may play that card without paying its mana cost for as long as Intet remains on the battlefield.
diff --git a/forge-gui/res/cardsfolder/i/intimidation_bolt.txt b/forge-gui/res/cardsfolder/i/intimidation_bolt.txt
index 6c51dce5eed..a8fdd4ff1cb 100644
--- a/forge-gui/res/cardsfolder/i/intimidation_bolt.txt
+++ b/forge-gui/res/cardsfolder/i/intimidation_bolt.txt
@@ -1,8 +1,7 @@
Name:Intimidation Bolt
ManaCost:1 R W
Types:Instant
-A:SP$ DealDamage | Cost$ 1 R W | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 3 | RememberTargets$ True | SubAbility$ DBPumpAll | SpellDescription$ CARDNAME deals 3 damage to target creature. Other creatures can't attack this turn.
-SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Remembered.Creature+Other | KW$ HIDDEN CARDNAME can't attack. | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+A:SP$ DealDamage | Cost$ 1 R W | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ 3 | SubAbility$ DBPumpAll | SpellDescription$ CARDNAME deals 3 damage to target creature. Other creatures can't attack this turn.
+SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Targeted.Creature+Other | KW$ HIDDEN CARDNAME can't attack.
AI:RemoveDeck:All
Oracle:Intimidation Bolt deals 3 damage to target creature. Other creatures can't attack this turn.
diff --git a/forge-gui/res/cardsfolder/m/mindclaw_shaman.txt b/forge-gui/res/cardsfolder/m/mindclaw_shaman.txt
index 8a2c7a96bd6..b5780d8dbb0 100644
--- a/forge-gui/res/cardsfolder/m/mindclaw_shaman.txt
+++ b/forge-gui/res/cardsfolder/m/mindclaw_shaman.txt
@@ -3,7 +3,6 @@ ManaCost:4 R
Types:Creature Viashino Shaman
PT:2/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigReveal | TriggerDescription$ When CARDNAME enters the battlefield, target opponent reveals their hand. You may cast an instant or sorcery spell from among those cards without paying its mana cost.
-SVar:TrigReveal:DB$ RevealHand | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | RememberTargets$ True | SubAbility$ TrigPlay
-SVar:TrigPlay:DB$ Play | Valid$ Card.RememberedPlayerCtrl | ValidSA$ Instant,Sorcery | ValidZone$ Hand | WithoutManaCost$ True | Optional$ True | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+SVar:TrigReveal:DB$ RevealHand | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | SubAbility$ TrigPlay
+SVar:TrigPlay:DB$ Play | Valid$ Card.TargetedPlayerCtrl | ValidSA$ Instant,Sorcery | ValidZone$ Hand | WithoutManaCost$ True | Optional$ True
Oracle:When Mindclaw Shaman enters the battlefield, target opponent reveals their hand. You may cast an instant or sorcery spell from among those cards without paying its mana cost.
diff --git a/forge-gui/res/cardsfolder/n/nightveil_specter.txt b/forge-gui/res/cardsfolder/n/nightveil_specter.txt
index 1b3ae2f5522..d6c87a422da 100644
--- a/forge-gui/res/cardsfolder/n/nightveil_specter.txt
+++ b/forge-gui/res/cardsfolder/n/nightveil_specter.txt
@@ -4,10 +4,6 @@ Types:Creature Specter
PT:2/3
K:Flying
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigExile | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, that player exiles the top card of their library.
-SVar:TrigExile:DB$ Dig | Defined$ TriggeredTarget | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True
-S:Mode$ Continuous | MayPlay$ True | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may play lands and cast spells from among cards exiled with CARDNAME.
-T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBForget
-SVar:DBForget:DB$ Pump | ForgetObjects$ TriggeredCard
-T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | Static$ True | ValidCard$ Card.Self | Execute$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+SVar:TrigExile:DB$ Dig | Defined$ TriggeredTarget | DigNum$ 1 | ChangeNum$ All | DestinationZone$ Exile
+S:Mode$ Continuous | MayPlay$ True | Affected$ Card.ExiledWithSource | AffectedZone$ Exile | Description$ You may play lands and cast spells from among cards exiled with CARDNAME.
Oracle:Flying\nWhenever Nightveil Specter deals combat damage to a player, that player exiles the top card of their library.\nYou may play lands and cast spells from among cards exiled with Nightveil Specter.
diff --git a/forge-gui/res/cardsfolder/n/nissa_steward_of_elements.txt b/forge-gui/res/cardsfolder/n/nissa_steward_of_elements.txt
index 43995244c0e..2174eef7165 100644
--- a/forge-gui/res/cardsfolder/n/nissa_steward_of_elements.txt
+++ b/forge-gui/res/cardsfolder/n/nissa_steward_of_elements.txt
@@ -5,8 +5,7 @@ Loyalty:X
SVar:X:Count$xPaid
A:AB$ Scry | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | ScryNum$ 2 | SpellDescription$ Scry 2.
A:AB$ Dig | Cost$ AddCounter<0/LOYALTY> | Planeswalker$ True | DigNum$ 1 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Land,Creature.cmcLEY | ForceRevealToController$ True | PromptToSkipOptionalAbility$ True | AILogic$ AlwaysConfirm | OptionalAbilityPrompt$ Would you like to put the permanent onto the battlefield? | DestinationZone$ Battlefield | LibraryPosition2$ 0 | SpellDescription$ Look at the top card of your library. If it's a land card or a creature card with mana value less than or equal to the number of loyalty counters on Nissa, Steward of Elements, you may put that card onto the battlefield.
-A:AB$ Untap | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Land.YouCtrl | TargetMin$ 0 | TargetMax$ 2 | RememberTargets$ True | SubAbility$ Animate | SpellDescription$ Untap up to two target lands you control. They become 5/5 Elemental creatures with flying and haste until end of turn. They're still lands.
-SVar:Animate:DB$ Animate | Defined$ Remembered | Power$ 5 | Toughness$ 5 | Types$ Creature,Elemental | Keywords$ Flying & Haste | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+A:AB$ Untap | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Land.YouCtrl | TargetMin$ 0 | TargetMax$ 2 | SubAbility$ Animate | SpellDescription$ Untap up to two target lands you control. They become 5/5 Elemental creatures with flying and haste until end of turn. They're still lands.
+SVar:Animate:DB$ Animate | Defined$ Targeted | Power$ 5 | Toughness$ 5 | Types$ Creature,Elemental | Keywords$ Flying & Haste
SVar:Y:Count$CardCounters.LOYALTY
Oracle:[+2]: Scry 2.\n[0]: Look at the top card of your library. If it's a land card or a creature card with mana value less than or equal to the number of loyalty counters on Nissa, Steward of Elements, you may put that card onto the battlefield.\n[-6]: Untap up to two target lands you control. They become 5/5 Elemental creatures with flying and haste until end of turn. They're still lands.
diff --git a/forge-gui/res/cardsfolder/n/nissa_vastwood_seer_nissa_sage_animist.txt b/forge-gui/res/cardsfolder/n/nissa_vastwood_seer_nissa_sage_animist.txt
index 15b7c6e5dba..124cb005ca5 100644
--- a/forge-gui/res/cardsfolder/n/nissa_vastwood_seer_nissa_sage_animist.txt
+++ b/forge-gui/res/cardsfolder/n/nissa_vastwood_seer_nissa_sage_animist.txt
@@ -4,7 +4,7 @@ Types:Legendary Creature Elf Scout
PT:2/2
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChange | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle.
SVar:TrigChange:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Forest.Basic | ChangeNum$ 1 | ShuffleNonMandatory$ True
-T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | IsPresent$ Land.YouCtrl | PresentCompare$ GE7 | Execute$ TrigExile | TriggerDescription$ Whenever a land enters the battlefield under your control, if you control seven or more lands, exile CARDNAME, then return her to the battlefield transformed under her owner's control.
+T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | IsPresent$ Land.YouCtrl | PresentCompare$ GE7 | Execute$ TrigExile | TriggerDescription$ Whenever a land enters the battlefield under your control, if you control seven or more lands, exile NICKNAME, then return her to the battlefield transformed under her owner's control.
SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBReturn
SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | Transformed$ True | ForgetOtherRemembered$ True | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
@@ -20,7 +20,6 @@ Types:Legendary Planeswalker Nissa
Loyalty:3
A:AB$ Dig | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | DigNum$ 1 | Reveal$ True | ChangeNum$ All | ChangeValid$ Land | DestinationZone$ Battlefield | DestinationZone2$ Hand | SpellDescription$ Reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put it into your hand.
A:AB$ Token | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | TokenAmount$ 1 | TokenScript$ ashaya_the_awoken_world | TokenOwner$ You | SpellDescription$ Create Ashaya, the Awoken World, a legendary 4/4 green Elemental creature token.
-A:AB$ Untap | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Land | TgtPrompt$ Choose target land | TargetMin$ 0 | TargetMax$ 6 | RememberTargets$ True | SubAbility$ DBAnimate | SpellDescription$ Untap up to six target lands. They become 6/6 Elemental creatures. They're still lands.
-SVar:DBAnimate:DB$ Animate | Defined$ Remembered | Power$ 6 | Toughness$ 6 | Types$ Creature,Elemental | Duration$ Permanent | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+A:AB$ Untap | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Land | TgtPrompt$ Choose target land | TargetMin$ 0 | TargetMax$ 6 | SubAbility$ DBAnimate | SpellDescription$ Untap up to six target lands. They become 6/6 Elemental creatures. They're still lands.
+SVar:DBAnimate:DB$ Animate | Defined$ Targeted | Power$ 6 | Toughness$ 6 | Types$ Creature,Elemental | Duration$ Permanent
Oracle:[+1]: Reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put it into your hand.\n[-2]: Create Ashaya, the Awoken World, a legendary 4/4 green Elemental creature token.\n[-7]: Untap up to six target lands. They become 6/6 Elemental creatures. They're still lands.
diff --git a/forge-gui/res/cardsfolder/t/the_ruinous_powers.txt b/forge-gui/res/cardsfolder/t/the_ruinous_powers.txt
index bc8fd85adeb..e1297c833a7 100644
--- a/forge-gui/res/cardsfolder/t/the_ruinous_powers.txt
+++ b/forge-gui/res/cardsfolder/t/the_ruinous_powers.txt
@@ -7,7 +7,7 @@ SVar:DBExile:DB$ Dig | Defined$ ChosenPlayer | DigNum$ 1 | DestinationZone$ Exil
SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | Triggers$ TriggerCastDoM | ForgetOnMoved$ Exile | ForgetOnCast$ False | RememberObjects$ Remembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearChosenPlayer$ True | ClearRemembered$ True
SVar:STPlay:Mode$ Continuous | MayPlay$ True | MayPlayIgnoreColor$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ Until end of turn, you may play that card and you may spend mana as though it were mana of any color to cast it.
-SVar:TriggerCastDoM:Mode$ SpellCast | ValidCard$ Card.IsRemembered | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigLoseLife | OneOff$ True | Secondary$ True | TriggerDescription$ When you cast a spell this way, its owner loses life equal to its mana value.
+SVar:TriggerCastDoM:Mode$ SpellCast | ValidCard$ Card.IsRemembered | ValidSA$ Spell.MayPlaySource | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigLoseLife | OneOff$ True | Secondary$ True | TriggerDescription$ When you cast a spell this way, its owner loses life equal to its mana value.
SVar:TrigLoseLife:DB$ LoseLife | Defined$ TriggeredCardOwner | LifeAmount$ X
SVar:X:TriggeredStackInstance$CardManaCostLKI
Oracle:At the beginning of your upkeep, choose an opponent at random. Exile the top card of that player's library. Until end of turn, you may play that card and you may spend mana as though it were mana of any color to cast it. When you cast a spell this way, its owner loses life equal to its mana value.
diff --git a/forge-gui/res/cardsfolder/t/theater_of_horrors.txt b/forge-gui/res/cardsfolder/t/theater_of_horrors.txt
index c01ca4b72c6..c78e4963d9c 100644
--- a/forge-gui/res/cardsfolder/t/theater_of_horrors.txt
+++ b/forge-gui/res/cardsfolder/t/theater_of_horrors.txt
@@ -2,12 +2,8 @@ Name:Theater of Horrors
ManaCost:1 B R
Types:Enchantment
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigExile | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, exile the top card of your library.
-SVar:TrigExile:DB$ Dig | Defined$ You | DestinationZone$ Exile | DigNum$ 1 | ChangeNum$ All | RememberChanged$ True
-S:Mode$ Continuous | Affected$ Card.IsRemembered | AffectedZone$ Exile | MayPlay$ True | Condition$ PlayerTurn | CheckSVar$ X | Description$ During your turn, if an opponent lost life this turn, you may play lands and cast spells from among cards exiled with CARDNAME.
+SVar:TrigExile:DB$ Dig | Defined$ You | DestinationZone$ Exile | DigNum$ 1 | ChangeNum$ All
+S:Mode$ Continuous | Affected$ Card.ExiledWithSource | AffectedZone$ Exile | MayPlay$ True | Condition$ PlayerTurn | CheckSVar$ X | Description$ During your turn, if an opponent lost life this turn, you may play lands and cast spells from among cards exiled with CARDNAME.
SVar:X:Count$LifeOppsLostThisTurn
-T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBForget
-SVar:DBForget:DB$ Pump | ForgetObjects$ TriggeredCard
-T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | Static$ True | ValidCard$ Card.Self | Execute$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
A:AB$ DealDamage | Cost$ 3 R | ValidTgts$ Opponent,Planeswalker | TgtPrompt$ Select target opponent or planeswalker | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to target opponent or planeswalker.
Oracle:At the beginning of your upkeep, exile the top card of your library.\nDuring your turn, if an opponent lost life this turn, you may play lands and cast spells from among cards exiled with Theater of Horrors.\n{3}{R}: Theater of Horrors deals 1 damage to target opponent or planeswalker.
diff --git a/forge-gui/res/cardsfolder/upcoming/fires_of_mount_doom.txt b/forge-gui/res/cardsfolder/upcoming/fires_of_mount_doom.txt
index 27b7da7010f..a1d8e1036f3 100644
--- a/forge-gui/res/cardsfolder/upcoming/fires_of_mount_doom.txt
+++ b/forge-gui/res/cardsfolder/upcoming/fires_of_mount_doom.txt
@@ -5,10 +5,10 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.S
SVar:TrigDamage:DB$ DealDamage | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls | NumDmg$ 2 | SubAbility$ ChompEquip
SVar:ChompEquip:DB$ DestroyAll | ValidCards$ Targeted.Equipment+Attached
A:AB$ Dig | Cost$ 2 R | DigNum$ 1 | DestinationZone$ Exile | RememberChanged$ True | SubAbility$ DBEffect | SpellDescription$ Exile the top card of your library. You may play that card this turn. When you play a card this way, CARDNAME deals 2 damage to each player.
-SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | Triggers$ TriggerCastDoM,TriggerLandPlayed | ForgetOnMoved$ Exile | ForgetOnCast$ False | RememberObjects$ Remembered | SubAbility$ DBCleanup
+SVar:DBEffect:DB$ Effect | StaticAbilities$ STPlay | Triggers$ TriggerCastDoM,TriggerLandPlayed | RememberObjects$ Remembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:STPlay:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may play that card this turn. When you play a card this way, CARDNAME deals 2 damage to each player.
-SVar:TriggerCastDoM:Mode$ SpellCast | ValidCard$ Card.IsRemembered | OneOff$ True | ValidActivatingPlayer$ You | Execute$ TrigDealDamage | TriggerDescription$ When you play a card this way, CARDNAME deals 2 damage to each player.
+SVar:TriggerCastDoM:Mode$ SpellCast | ValidCard$ Card.IsRemembered | ValidSA$ Spell.MayPlaySource | OneOff$ True | ValidActivatingPlayer$ You | Execute$ TrigDealDamage | TriggerDescription$ When you play a card this way, CARDNAME deals 2 damage to each player.
SVar:TriggerLandPlayed:Mode$ LandPlayed | ValidCard$ Land.IsRemembered | OneOff$ True | Execute$ TrigDealDamage | Secondary$ True | TriggerDescription$ When you play a card this way, CARDNAME deals 2 damage to each player.
SVar:TrigDealDamage:DB$ DealDamage | Defined$ Player | NumDmg$ 2
Oracle:When Fires of Mount Doom enters the battlefield, it deals 2 damage to target creature an opponent controls. Destroy all Equipment attached to that creature.\n{2}{R}: Exile the top card of your library. You may play that card this turn. When you play a card this way, Fires of Mount Doom deals 2 damage to each player.
\ No newline at end of file
diff --git a/forge-gui/res/cardsfolder/w/waking_the_trolls.txt b/forge-gui/res/cardsfolder/w/waking_the_trolls.txt
index 2b47e159230..9f6490eec83 100644
--- a/forge-gui/res/cardsfolder/w/waking_the_trolls.txt
+++ b/forge-gui/res/cardsfolder/w/waking_the_trolls.txt
@@ -4,10 +4,9 @@ Types:Enchantment Saga
K:Saga:3:DBDestroy,DBChangeZone,DBPump
SVar:DBDestroy:DB$ Destroy | ValidTgts$ Land | TgtPrompt$ Choose target land. | SpellDescription$ Destroy target land.
SVar:DBChangeZone:DB$ ChangeZone | ValidTgts$ Land | TgtPrompt$ Choose target land card. | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | SpellDescription$ Put target land card from a graveyard onto the battlefield under your control.
-SVar:DBPump:DB$ Pump | ValidTgts$ Player.Opponent | RememberTargets$ True | IsCurse$ True | TgtPrompt$ Choose target player. | SubAbility$ DBToken | SpellDescription$ Choose target player. If they control fewer lands than you, create a number of 4/4 green Troll Warrior creature tokens with trample equal to the difference.
-SVar:DBToken:DB$ Token | TokenAmount$ X | TokenScript$ g_4_4_troll_warrior_trample | TokenOwner$ You | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
+SVar:DBPump:DB$ Pump | ValidTgts$ Opponent | IsCurse$ True | SubAbility$ DBToken | SpellDescription$ Choose target player. If they control fewer lands than you, create a number of 4/4 green Troll Warrior creature tokens with trample equal to the difference.
+SVar:DBToken:DB$ Token | TokenAmount$ X | TokenScript$ g_4_4_troll_warrior_trample | TokenOwner$ You
SVar:X:Count$Valid Land.YouCtrl/Minus.Y
-SVar:Y:Count$Valid Land.RememberedPlayerCtrl
+SVar:Y:Count$Valid Land.TargetedPlayerCtrl
DeckHas:Ability$Token
Oracle:(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)\nI — Destroy target land.\nII — Put target land card from a graveyard onto the battlefield under your control.\nIII — Choose target opponent. If they control fewer lands than you, create a number of 4/4 green Troll Warrior creature tokens with trample equal to the difference.
diff --git a/forge-gui/res/cardsfolder/w/winnow.txt b/forge-gui/res/cardsfolder/w/winnow.txt
index 7158ea1e7a9..23127ec32a2 100644
--- a/forge-gui/res/cardsfolder/w/winnow.txt
+++ b/forge-gui/res/cardsfolder/w/winnow.txt
@@ -1,10 +1,9 @@
Name:Winnow
ManaCost:1 W
Types:Instant
-A:SP$ Destroy | Cost$ 1 W | ValidTgts$ Permanent.nonLand | RememberTargets$ True | ConditionCheckSVar$ WinnowCheck | ConditionSVarCompare$ GE2 | SubAbility$ DBDraw | SpellDescription$ Destroy target nonland permanent if another permanent with the same name is on the battlefield. Draw a card.
-SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1 | SubAbility$ DBCleanup
-SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
-SVar:WinnowCheck:Count$Valid Permanent.sharesNameWith Remembered
+A:SP$ Destroy | Cost$ 1 W | ValidTgts$ Permanent.nonLand | ConditionCheckSVar$ WinnowCheck | ConditionSVarCompare$ GE2 | SubAbility$ DBDraw | SpellDescription$ Destroy target nonland permanent if another permanent with the same name is on the battlefield. Draw a card.
+SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1
+SVar:WinnowCheck:Count$Valid Permanent.sharesNameWith Targeted
AI:RemoveDeck:All
AI:RemoveDeck:Random
Oracle:Destroy target nonland permanent if another permanent with the same name is on the battlefield.\nDraw a card.
diff --git a/forge-gui/res/cardsfolder/x/xira_the_golden_sting.txt b/forge-gui/res/cardsfolder/x/xira_the_golden_sting.txt
index b978c34a940..d1ef42c4e6a 100644
--- a/forge-gui/res/cardsfolder/x/xira_the_golden_sting.txt
+++ b/forge-gui/res/cardsfolder/x/xira_the_golden_sting.txt
@@ -5,7 +5,7 @@ PT:3/3
K:Flying
K:Haste
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigEggCounter | TriggerDescription$ Whenever CARDNAME attacks, put an egg counter on another target creature without an egg counter on it. When that creature dies, if it has an egg counter on it, draw a card and create a 1/1 black Insect creature token with flying.
-SVar:TrigEggCounter:DB$ PutCounter | CounterType$ EGG | CounterNum$ 1 | ValidTgts$ Creature.Other+counters_EQ0_EGG | RememberTargets$ True | TgtPrompt$ Put an egg counter on another target creature without an egg counter on it. | SubAbility$ DelayedTrigger
+SVar:TrigEggCounter:DB$ PutCounter | CounterType$ EGG | CounterNum$ 1 | ValidTgts$ Creature.Other+counters_EQ0_EGG | TgtPrompt$ Put an egg counter on another target creature without an egg counter on it. | SubAbility$ DelayedTrigger
SVar:DelayedTrigger:DB$ DelayedTrigger | Mode$ ChangesZone | RememberObjects$ Targeted | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.IsTriggerRemembered+counters_GE1_EGG | Execute$ TrigDraw | TriggerDescription$ When this creature dies, if it has an egg counter on it, draw a card and create a 1/1 black Insect creature token with flying.
SVar:TrigDraw:DB$ Draw | Defined$ You | NumCards$ 1 | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenScript$ b_1_1_insect_flying
From 5cfae3aea76bcbd5ef0dcf581820921d2f9dfc95 Mon Sep 17 00:00:00 2001
From: paulsnoops
Date: Mon, 17 Jul 2023 10:19:19 +0100
Subject: [PATCH 7/7] Edition updates: CMM, EA3, HA7
---
forge-gui/res/editions/Commander Masters.txt | 259 +++++++++++++++++--
forge-gui/res/editions/The List.txt | 79 +++++-
2 files changed, 308 insertions(+), 30 deletions(-)
diff --git a/forge-gui/res/editions/Commander Masters.txt b/forge-gui/res/editions/Commander Masters.txt
index 815772e10d8..b50ef2de03c 100644
--- a/forge-gui/res/editions/Commander Masters.txt
+++ b/forge-gui/res/editions/Commander Masters.txt
@@ -9,100 +9,191 @@ ScryfallCode=CMM
1 S The Prismatic Piper @Seb McKinnon
2 M Kozilek, the Great Distortion @Aleksi Briclot
3 M Morophon, the Boundless @Victor Adame Minguez
+5 M Ulamog, the Ceaseless Hunger @Michael Komarck
6 C Ulamog's Crusher @Todd Lockwood
10 R Alms Collector @Bram Sels
-11 R Anafenza, Kin-Tree Spirit @Ryan Yee
+11 U Anafenza, Kin-Tree Spirit @Ryan Yee
13 R Angelic Field Marshal @Scott Murphy
+14 M Avacyn, Angel of Hope @Jason Chan
16 R Balan, Wandering Knight @Svetlin Velinov
-17 U Battle Screech @Anastasia Ovchinnikova
+17 C Battle Screech @Anastasia Ovchinnikova
18 U Cartographer's Hawk @Donato Giancola
+21 U Darksteel Mutation @Daniel Ljunggren
22 U Elite Scaleguard @Steve Prescott
+24 R Flawless Maneuver @Zoltan Boros
27 R Grand Abolisher @Eric Deschamps
+28 R Heavenly Blademaster @Zack Stella
+29 M Heliod, Sun-Crowned @Lius Lasahido
+32 R Jazal Goldmane @Aaron Miller
+34 U Kemba, Kha Regent @Ernanda Souza
35 U Kirtar's Wrath @Kev Walker
37 M Land Tax @Chuck Lukacs
+39 M Loyal Retainers @Kieran Yanner
+42 R Mangara, the Diplomat @Howard Lyon
+45 R Nahiri, the Lithomancer @Eric Deschamps
50 U Pianna, Nomad Captain @D. Alexander Gregory
51 R Puresteel Paladin @Jason Chan
+53 R Righteous Confluence @Kieran Yanner
+54 R Sephara, Sky's Blade @Livia Prima
+55 R Sevinne's Reclamation @Zoltan Boros
+56 C Shelter @Alayna Danner
+57 M Smothering Tithe @Mark Behm
+59 R Steelshaper's Gift @Greg Hildebrandt
60 R Sublime Exhalation @Lake Hurwitz
+68 R Wakening Sun's Avatar @Tyler Jacobson
+71 R Zetalpa, Primal Dawn @Chris Rallis
73 R Aminatou's Augury @Seb McKinnon
74 R Azami, Lady of Scrolls @Ittoku
-75 R Braids, Conjurer Adept @Zoltan Boros & Gabor Szikszai
-79 R Capture of Jingzhou @Jack Wei
+76 R Braids, Conjurer Adept @Zoltan Boros & Gabor Szikszai
+77 M Bribery @Kai Carpenter
+79 M Capture of Jingzhou @Jack Wei
+80 R Commandeer @John Matson
84 R Cyclonic Rift @Chris Rahn
+85 R Day's Undoing @Jonas De Ro
89 R Evacuation @Franz Vohwinkel
92 R Faerie Artisans @Tony Foti
+94 R Fierce Guardianship @Randy Vargas
+103 R Lorthos, the Tidemaker @Kekai Kotaki
105 R Minds Aglow @Yeong-Hao Han
108 R Mystic Confluence @Kieran Yanner
110 R Personal Tutor @Julie Dillon
+113 U Reality Shift @Howard Lyon
118 R Sai, Master Thopterist @Adam Paquette
120 M Spellseeker @Igor Kieryluk
122 R Stormsurge Kraken @Svetlin Velinov
+123 M Sun Quan, Lord of Wu @Xu Xiaoming
125 R Teferi, Temporal Archmage @Tyler Jacobson
128 R Torrential Gearhulk @Svetlin Velinov
130 M Urza, Lord High Artificer @Grzegorz Rutkowski
134 C Windrider Wizard @Slawomir Maniak
137 M Archfiend of Despair @Josh Hass
+139 R Bloodchief Ascension @Adi Granov
144 R Chainer, Dementia Master @Mark Zug
146 R Curtains' Call @James Ryman
+147 R Deadly Rollick @Izzy
+148 R Decree of Pain @Carl Critchlow
+150 M Demonic Tutor @Zack Stella
+151 R Demonlord Belzenlok @Tyler Jacobson
+155 R Endrek Sahr, Master Breeder @Lucas Graciano
+156 U Exsanguinate @Marie Magny
157 U Extinguish All Hope @Aaron J. Riley
161 R Ghoulcaller Gisa @Karla Ortiz
+165 M Grave Pact @Billy Christian
+167 R Imp's Mischief @Thomas M. Baxa
169 R Kindred Dominance @Bram Sels
-176 M Ob Nixilis of the Black Oath @Daarken
+173 M Mikaeus, the Unhallowed @Chris Rahn
+176 R Ob Nixilis of the Black Oath @Daarken
+177 R Ogre Slumlord @Trevor Claxton
+180 R Rankle, Master of Pranks @Dmitry Burmak
+181 M Razaketh, the Foulblooded @Chris Rallis
+184 R Rune-Scarred Demon @Michael Komarck
+187 R Sower of Discord @Wisnu Tan
191 R Toxic Deluge @Svetlin Velinov
+193 M Twilight Prophet @Seb McKinnon
+196 R Vindictive Lich @Toma Feizo Gas
197 R Wake the Dead @Christopher Moeller
200 R Wretched Confluence @Kieran Yanner
202 U Yargle, Glutton of Urborg @Jehan Choo
205 R Ashling the Pilgrim @Wayne Reynolds
+206 R Avatar of Slaughter @Jason A. Engle
+207 M Balefire Dragon @Eric Deschamps
208 C Blood Aspirant @Tyler Walpole
213 R Daretti, Scrap Savant @Dan Scott
+214 R Deflecting Swat @Izzy
218 R Drakuseth, Maw of Flames @Grzegorz Rutkowski
222 R Fiery Confluence @Kieran Yanner
+227 R Godo, Bandit Warlord @Paolo Parente
+228 R Grenzo, Havoc Raiser @Svetlin Velinov
231 R Heartless Hidetsugu @Carl Critchlow
232 R Hellkite Charger @Jaime Jones
236 M Insurrection @Mark Zug
238 R Krenko, Mob Boss @Karl Kopinski
241 R Magus of the Wheel @Carl Frank
+244 M Neheb, the Eternal @Chris Rahn
245 R Nesting Dragon @Jehan Choo
-259 M Star of Extinction @Chris Rahn
+246 M Purphoros, God of the Forge @Eric Deschamps
+247 U Rakka Mar @Jason Chan
+252 M Savage Beating @Matt Thompson
+253 R Scourge of the Throne @Michael Komarck
+259 R Star of Extinction @Chris Rahn
+260 U Storm-Kiln Artist @Manuel Castañón
+263 R Tempt with Vengeance @Ryan Barger
265 R Treasure Nabber @Alex Konstad
267 U Vandalblast @Seb McKinnon
+272 R Arachnogenesis @Johannes Voss
274 R Azusa, Lost but Seeking @Winona Nelson
+276 R Bloodspore Thrinax @Ralph Horsley
+280 M Craterhoof Behemoth @Chris Rahn
+283 M Doubling Season @Chuck Lukacs
289 M Finale of Devastation @Bayard Wu
+290 R Freyalise, Llanowar's Fury @Adam Paquette
+292 R Ghalta, Primal Hunger @Chase Stone
294 M The Great Henge @Adam Paquette
295 R Heroic Intervention @James Ryman
297 C Ilysian Caryatid @Winona Nelson
299 R Jolrael, Mwonvuli Recluse @Izzy
+300 C Kodama's Reach @John Avon
303 R Lifeblood Hydra @Alex Horley-Orlandelli
308 R Obscuring Haze @Campbell White
309 R Ohran Frostfang @Torstein Nordstrand
310 M Omnath, Locus of Mana @Mike Bierek
316 R Regal Behemoth @Jakub Kasper
-317 R Rishkar, Peema Renegade @Todd Lockwood
+317 U Rishkar, Peema Renegade @Todd Lockwood
+319 R Sakiko, Mother of Summer @Livia Prima
320 M Selvala, Heart of the Wilds @Tyler Jacobson
321 C Skyshroud Claim @Anna Steinbauer
+324 R Song of the Dryads @Lars Grant-West
+325 R Stonehoof Chieftain @Camille Alquier
+327 R Tooth and Nail @Greg Hildebrandt
+329 R Verdant Confluence @Kieran Yanner
331 R Wayward Swordtooth @Chris Rahn
334 R Yisan, the Wanderer Bard @Chase Stone
+337 R Experiment Kraj @Mark Tedin
+338 R Gisela, Blade of Goldnight @Jason Chan
+339 U Hamza, Guardian of Arashin @Wisnu Tan
+340 R Hanna, Ship's Navigator @Chris Rallis
342 R Karador, Ghost Chieftain @Todd Lockwood
+343 R Kykar, Wind's Fury @G-host Lee
344 R Maelstrom Wanderer @Victor Adame Minguez
-348 M Mizzix of the Izmagnus @Cliff Childs
+347 R Mirri, Weatherlight Duelist @Magali Villeneuve
+348 R Mizzix of the Izmagnus @Cliff Childs
+349 R Nekusar, the Mindrazer @Mark Winters
350 R Queen Marchesa @Kieran Yanner
+353 M The Scarab God @Lius Lasahido
+354 R Sek'Kuar, Deathkeeper @Jesper Ejsing
+355 R Sidisi, Brood Tyrant @Karl Kopinski
361 M The Ur-Dragon @Jaime Jones
-367 C Arcane Signet @Dan Scott
+362 R Xantcha, Sleeper Agent @Mark Winters
+363 R Yennett, Cryptic Sovereign @Chris Rahn
+364 R Yuriko, the Tiger's Shadow @Yongjae Choi
+365 R Zacama, Primal Calamity @Jaime Jones
+366 R Zilortha, Strength Incarnate @Chase Stone
+367 U Arcane Signet @Dan Scott
+368 U Ashnod's Altar @Greg Staples
371 R Boompile @Filip Burburan
372 C Brass Knuckles @Yeong-Hao Han
375 R Champion's Helm @Alan Pollack
+376 R Chromatic Lantern @Jung Park
379 R Emerald Medallion @Daniel Ljunggren
+381 M Extraplanar Lens @Lars Grant-West
382 U Fellwar Stone @John Avon
+387 R Gilded Lotus @Volkan Baǵa
388 R Hammer of Nazahn @Victor Adame Minguez
+392 R Idol of Oblivion @Piotr Dura
393 M The Immortal Sun @Kieran Yanner
+394 R Inspiring Statuary @Kirsten Zirngibl
395 R Jet Medallion @Daniel Ljunggren
396 M Jeweled Lotus @Alayna Danner
401 R Pearl Medallion @Daniel Ljunggren
405 R Ruby Medallion @Daniel Ljunggren
407 R Sapphire Medallion @Daniel Ljunggren
+408 R Scytheclaw @James Paick
410 U Sol Ring @Mike Bierek
+413 R Sword of the Animist @Daniel Ljunggren
415 U Thran Dynamo @Ron Spears
420 C Command Tower @Ryan Yee
423 C Path of Ancestry @Alayna Danner
+425 U Reliquary Tower @Jesper Ejsing
426 U Rogue's Passage @Christine Choi
429 C Thriving Bluff @Johannes Voss
430 C Thriving Grove @Ravenna Tran
@@ -125,99 +216,207 @@ ScryfallCode=CMM
450 L Forest @Rebecca Guay
451 L Forest @Mark Poole
452 M Kozilek, the Great Distortion @Aleksi Briclot
+453 M Morophon, the Boundless @Victor Adame Minguez
+454 M Ulamog, the Ceaseless Hunger @Michael Komarck
455 R Alms Collector @Bram Sels
456 R Angelic Field Marshal @Scott Murphy
+457 M Avacyn, Angel of Hope @Jason Chan
458 R Balan, Wandering Knight @Svetlin Velinov
+459 R Flawless Maneuver @Zoltan Boros
460 R Grand Abolisher @Eric Deschamps
+461 R Heavenly Blademaster @Zack Stella
462 M Heliod, Sun-Crowned @Lius Lasahido
+463 R Jazal Goldmane @Aaron Miller
464 M Land Tax @Chuck Lukacs
+465 M Loyal Retainers @Kieran Yanner
+466 R Mangara, the Diplomat @Howard Lyon
+467 R Nahiri, the Lithomancer @Eric Deschamps
+468 R Odric, Master Tactician @Michael Komarck
469 R Puresteel Paladin @Jason Chan
+470 R Righteous Confluence @Kieran Yanner
+471 R Sephara, Sky's Blade @Livia Prima
+472 R Sevinne's Reclamation @Zoltan Boros
+473 M Smothering Tithe @Mark Behm
475 R Sublime Exhalation @Lake Hurwitz
+476 R Wakening Sun's Avatar @Tyler Jacobson
+478 R Zetalpa, Primal Dawn @Chris Rallis
479 R Aminatou's Augury @Seb McKinnon
+480 R Azami, Lady of Scrolls @Ittoku
481 R Braids, Conjurer Adept @Zoltan Boros & Gabor Szikszai
-483 R Capture of Jingzhou @Jack Wei
+482 M Bribery @Kai Carpenter
+483 M Capture of Jingzhou @Jack Wei
+484 R Commandeer @John Matson
+485 R Cyclonic Rift @Chris Rahn
+487 R Evacuation @Franz Vohwinkel
488 R Faerie Artisans @Tony Foti
490 R Lorthos, the Tidemaker @Kekai Kotaki
491 R Minds Aglow @Yeong-Hao Han
492 R Mystic Confluence @Kieran Yanner
493 R Personal Tutor @Julie Dillon
+494 R Sai, Master Thopterist @Adam Paquette
495 M Spellseeker @Igor Kieryluk
497 R Stormsurge Kraken @Svetlin Velinov
+498 M Sun Quan, Lord of Wu @Xu Xiaoming
500 R Teferi, Temporal Archmage @Tyler Jacobson
+501 R Torrential Gearhulk @Svetlin Velinov
502 M Urza, Lord High Artificer @Grzegorz Rutkowski
503 M Archfiend of Despair @Josh Hass
+504 R Bloodchief Ascension @Adi Granov
505 R Chainer, Dementia Master @Mark Zug
+506 R Curtains' Call @James Ryman
507 R Deadly Rollick @Izzy
-517 M Ob Nixilis of the Black Oath @Daarken
+509 M Demonic Tutor @Zack Stella
+510 R Demonlord Belzenlok @Tyler Jacobson
+511 R Endrek Sahr, Master Breeder @Lucas Graciano
+512 R Ghoulcaller Gisa @Karla Ortiz
+513 M Grave Pact @Billy Christian
+514 R Imp's Mischief @Thomas M. Baxa
+515 R Kindred Dominance @Bram Sels
+516 M Mikaeus, the Unhallowed @Chris Rahn
+517 R Ob Nixilis of the Black Oath @Daarken
+518 R Ogre Slumlord @Trevor Claxton
+519 R Rankle, Master of Pranks @Dmitry Burmak
+520 M Razaketh, the Foulblooded @Chris Rallis
522 R Sower of Discord @Wisnu Tan
523 R Toxic Deluge @Svetlin Velinov
+524 M Twilight Prophet @Seb McKinnon
+525 R Vindictive Lich @Toma Feizo Gas
526 R Wake the Dead @Christopher Moeller
527 R Wretched Confluence @Kieran Yanner
+528 R Ashling the Pilgrim @Wayne Reynolds
529 R Avatar of Slaughter @Jason A. Engle
+530 M Balefire Dragon @Eric Deschamps
531 R Daretti, Scrap Savant @Dan Scott
+532 R Deflecting Swat @Izzy
+534 R Divergent Transformations @Kev Walker
+535 R Drakuseth, Maw of Flames @Grzegorz Rutkowski
+536 R Fiery Confluence @Kieran Yanner
+537 R Godo, Bandit Warlord @Paolo Parente
+538 R Grenzo, Havoc Raiser @Svetlin Velinov
+539 R Heartless Hidetsugu @Carl Critchlow
+540 R Hellkite Charger @Jaime Jones
+541 R Inferno Titan @Kev Walker
542 M Insurrection @Mark Zug
543 R Krenko, Mob Boss @Karl Kopinski
544 R Magus of the Wheel @Carl Frank
+545 M Neheb, the Eternal @Chris Rahn
546 R Nesting Dragon @Jehan Choo
-548 R Savage Beating @Matt Thompson
-550 M Star of Extinction @Chris Rahn
+547 M Purphoros, God of the Forge @Eric Deschamps
+548 M Savage Beating @Matt Thompson
+549 R Scourge of the Throne @Michael Komarck
+550 R Star of Extinction @Chris Rahn
+551 R Tempt with Vengeance @Ryan Barger
552 R Treasure Nabber @Alex Konstad
554 R Azusa, Lost but Seeking @Winona Nelson
+555 R Bloodspore Thrinax @Ralph Horsley
+556 M Craterhoof Behemoth @Chris Rahn
+557 M Doubling Season @Chuck Lukacs
+558 R Ezuri's Predation @Uriah Voth
559 M Finale of Devastation @Bayard Wu
+560 R Freyalise, Llanowar's Fury @Adam Paquette
+561 R Ghalta, Primal Hunger @Chase Stone
+562 M The Great Henge @Adam Paquette
563 R Heroic Intervention @James Ryman
564 R Jolrael, Mwonvuli Recluse @Izzy
565 R Lifeblood Hydra @Alex Horley-Orlandelli
566 R Obscuring Haze @Campbell White
+567 R Ohran Frostfang @Torstein Nordstrand
568 M Omnath, Locus of Mana @Mike Bierek
569 R Regal Behemoth @Jakub Kasper
571 M Selvala, Heart of the Wilds @Tyler Jacobson
+572 R Song of the Dryads @Lars Grant-West
+573 R Stonehoof Chieftain @Camille Alquier
+574 R Tooth and Nail @Greg Hildebrandt
+575 R Verdant Confluence @Kieran Yanner
576 R Wayward Swordtooth @Chris Rahn
577 R Yisan, the Wanderer Bard @Chase Stone
578 R Experiment Kraj @Mark Tedin
+579 R Gisela, Blade of Goldnight @Jason Chan
+580 R Hanna, Ship's Navigator @Chris Rallis
581 R Karador, Ghost Chieftain @Todd Lockwood
+582 R Kykar, Wind's Fury @G-host Lee
583 R Maelstrom Wanderer @Victor Adame Minguez
-586 M Mizzix of the Izmagnus @Cliff Childs
-587 M Nekusar, the Mindrazer @Mark Winters
+584 R Meren of Clan Nel Toth @Mark Winters
+585 R Mirri, Weatherlight Duelist @Magali Villeneuve
+586 R Mizzix of the Izmagnus @Cliff Childs
+587 R Nekusar, the Mindrazer @Mark Winters
588 R Queen Marchesa @Kieran Yanner
+589 R Rafiq of the Many @Michael Komarck
+590 M The Scarab God @Lius Lasahido
+591 R Sek'Kuar, Deathkeeper @Jesper Ejsing
+592 R Sidisi, Brood Tyrant @Karl Kopinski
+593 R Teysa Karlov @Magali Villeneuve
594 M The Ur-Dragon @Jaime Jones
+595 R Xantcha, Sleeper Agent @Mark Winters
+599 R Zilortha, Strength Incarnate @Chase Stone
600 R Boompile @Filip Burburan
601 R Champion's Helm @Alan Pollack
602 R Chromatic Lantern @Jung Park
603 R Emerald Medallion @Daniel Ljunggren
+604 M Extraplanar Lens @Lars Grant-West
606 R Hammer of Nazahn @Victor Adame Minguez
+607 R Idol of Oblivion @Piotr Dura
608 M The Immortal Sun @Kieran Yanner
+609 R Inspiring Statuary @Kirsten Zirngibl
610 R Jet Medallion @Daniel Ljunggren
611 M Jeweled Lotus @Alayna Danner
612 R Pearl Medallion @Daniel Ljunggren
613 R Ruby Medallion @Daniel Ljunggren
614 R Sapphire Medallion @Daniel Ljunggren
-625 R Grand Abolisher @
+616 R Sword of the Animist @Daniel Ljunggren
+623 U Darksteel Mutation @Richard Kane Ferguson
+625 R Grand Abolisher @Richard Kane Ferguson
627 R Puresteel Paladin @Richard Kane Ferguson
+629 R Steelshaper's Gift @Paolo Parente
633 R Personal Tutor @Jeff Miracola
-635 M Spellseeker @
+634 U Reality Shift @Warren Mahy
+635 M Spellseeker @Douglas Shuler
+636 R Bloodchief Ascension @Warren Mahy
+639 M Grave Pact @Kev Walker
640 R Kindred Dominance @Thomas M. Baxa
643 R Magus of the Wheel @Scott M. Fischer
+644 U Storm-Kiln Artist @Chuck Lukacs
645 R Treasure Nabber @Pete Venters
-646 U Vandalblast @
-651 R Regal Behemoth @
+646 U Vandalblast @Dermot Power
+649 C Kodama's Reach @Ron Spencer
+650 R Ohran Frostfang @Ron Spears
+651 R Regal Behemoth @Kev Walker
+652 R Tooth and Nail @Eric Velhagen
653 U Arcane Signet @Drew Tucker
654 R Champion's Helm @Paolo Parente
-656 R Extraplanar Lens @Ron Spears
+656 M Extraplanar Lens @Ron Spears
657 U Fellwar Stone @Randy Gallegos
-658 U Thran Dynamo @
-661 C Path of Ancestry @
+658 U Thran Dynamo @Chuck Lukacs
+659 C Command Tower @Donato Giancola
+661 C Path of Ancestry @Mark Poole
663 U Reliquary Tower @Mark Poole
668 M Kozilek, the Great Distortion @Grant Griffin
+669 M Morophon, the Boundless @Jack Hughes
+670 M Ulamog, the Ceaseless Hunger @Cosmin Podar
671 U Kemba, Kha Regent @Peter Diamond
+672 R Azami, Lady of Scrolls @Grant Griffin
+673 R Talrand, Sky Summoner @Tyler Walpole
+674 M Urza, Lord High Artificer @Grant Griffin
+675 M Mikaeus, the Unhallowed @Benjamin Ee
+677 R Grenzo, Havoc Raiser @Tyler Walpole
+678 M Neheb, the Eternal @Alex Stone
679 R Azusa, Lost but Seeking @Benjamin Ee
-680 M Omnath, Locus of Mana @
+680 M Omnath, Locus of Mana @Alex Dos Diaz
681 M Selvala, Heart of the Wilds @Jack Hughes
+682 R Gisela, Blade of Goldnight @Alex Dos Diaz
683 R Kykar, Wind's Fury @April Prime
-684 R Maelstrom Wanderer @
+684 R Maelstrom Wanderer @Benjamin Ee
+685 R Meren of Clan Nel Toth @Vance Kelly
+688 R Teysa Karlov @Jack Hughes
689 M The Ur-Dragon @Tyler Walpole
+692 R Flawless Maneuver @Warren Mahy
693 M Smothering Tithe @Jeff Miracola
-695 R Deadly Rollick @Izzy
-699 M Insurrection @
+694 R Fierce Guardianship @
+695 R Deadly Rollick @Ron Spencer
+696 M Demonic Tutor @Donato Giancola
+697 M Balefire Dragon @Scott M. Fischer
+698 R Deflecting Swat @Greg Staples
+699 M Insurrection @Jeff Miracola
700 M Finale of Devastation @Daren Bader
701 R Obscuring Haze @Daren Bader
702 M Jeweled Lotus @Olena Richards
@@ -234,8 +433,12 @@ ScryfallCode=CMM
781 M Commodore Guff @Matt Stewart
782 M Sliver Gravemother @Chris Rahn
1057 M Kozilek, the Great Distortion @Grant Griffin
-1060 M Urza, Lord High Artificer @
-1063 M Omnath, Locus of Mana @
+1058 M Morophon, the Boundless @Jack Hughes
+1059 M Ulamog, the Ceaseless Hunger @Cosmin Podar
+1060 M Urza, Lord High Artificer @Grant Griffin
+1061 M Mikaeus, the Unhallowed @Benjamin Ee
+1062 M Neheb, the Eternal @Alex Stone
+1063 M Omnath, Locus of Mana @Alex Dos Diaz
1064 M Selvala, Heart of the Wilds @Jack Hughes
1065 M The Ur-Dragon @Tyler Walpole
1066 M Jeweled Lotus @Olena Richards
diff --git a/forge-gui/res/editions/The List.txt b/forge-gui/res/editions/The List.txt
index 0d024109fb8..6112904fede 100644
--- a/forge-gui/res/editions/The List.txt
+++ b/forge-gui/res/editions/The List.txt
@@ -781,14 +781,14 @@ F567 R Puresteel Angel @Lukas Litzsinger
773 R Repay in Kind @Vance Kovacs
774 R Volrath's Dungeon @Stephen Daniele
775 C Dragon's Approach @Andrew Mar
-776 U Dragon's Rage Channeler @Martina Fackova
+776 U Dragon's Rage Channeler @Martina Fačková
777 M Goldspan Dragon @Andrew Mar
778 R Lathliss, Dragon Queen @Alex Konstad
779 U Magic Missile @PINDURSKI
780 U Thundering Sparkmage @Billy Christian
781 R Worldgorger Dragon @Wayne England
782 U Devoted Druid @Kimonas Theodossiou
-783 U Druid's Call @Greg Hildebrandt
+783 U Druid's Call @Greg Hildebrandt & Tim Hildebrandt
784 U Edgewall Innkeeper @Matt Stewart
785 R Gilt-Leaf Archdruid @Steve Prescott
786 M Old Gnawbone @Filip Burburan
@@ -1095,3 +1095,78 @@ F567 R Puresteel Angel @Lukas Litzsinger
1087 R Sea of Clouds @Florian de Gesincourt
1088 R The World Tree @Anastasia Ovchinnikova
1089 U Zhalfirin Void @Chase Stone
+1090 U All That Glitters @Iain McCaig
+1091 U Baird, Steward of Argive @Christine Choi
+1092 C Battleflight Eagle @Kev Walker
+1093 R Court of Grace @Denman Rooke
+1094 R Darien, King of Kjeldor @Michael Phillippi
+1095 C Doomed Traveler @Lars Grant-West
+1096 R Earnest Fellowship @Heather Hudson
+1097 U Far Traveler @Alix Branwyn
+1098 C Fortifying Provisions @Scott Murphy
+1099 U Generous Gift @Kev Walker
+1100 M Kenrith, the Returned King @Kieran Yanner
+1101 R Knight-Captain of Eos @Chris Rahn
+1102 R Knight Exemplar @Jason Chan
+1103 C Oaken Brawler @Jim Murray
+1104 R Ancestral Memories @Dan Frazier
+1105 R Arcane Melee @Jaime Jones
+1106 R Commandeer @John Matson
+1107 R Counterlash @Austin Hsu
+1108 R Denying Wind @Tony Szczudlo
+1109 R Exhaustion @DiTerlizzi
+1110 R Mindlock Orb @rk post
+1111 R Oath of Scholars @Michael Sutfin
+1112 R Rayne, Academy Chancellor @Matthew D. Wilson
+1113 C Stormwatch Eagle @Aaron Boyd
+1114 R Stroke of Genius @Stephen Daniele
+1115 C Traveler's Cloak @Rebecca Guay
+1116 C Barrow Ghoul @Bryan Talbot
+1117 C Barrow Witches @Alex Brock
+1118 U Bog Wraith @Daarken
+1119 U Evil Eye of Urborg @Clint Langley
+1120 U Grim Strider @Christine Choi
+1121 U Orc Sureshot @Kev Walker
+1122 R Pitiless Horde @Viktor Titov
+1123 U Crush the Weak @Lucas Graciano
+1124 R Dwarven Bloodboiler @Arnie Swekel
+1125 C Dwarven Grunt @Mike Ploog
+1126 U Dwarven Miner @Jock
+1127 U Glittering Stockpile @Brock Grossman
+1128 U Hoarding Dragon @Matt Cavotta
+1129 C Miner's Bane @Adam Paquette
+1130 U Orcish Artillery @Jeff Miracola
+1131 R Reforge the Soul @Jaime Jones
+1132 C Battlewand Oak @Steve Prescott
+1133 U Blossom Prancer @Ryan Yee
+1134 R Budoka Gardener @Kev Walker
+1135 C Courage in Crisis @Micah Epstein
+1136 R Dauntless Dourbark @Jeremy Jarvis
+1137 U Elven Palisade @Mark Zug
+1138 R Elven Warhounds @Kev Walker
+1139 U Gather Courage @Brian Despain
+1140 R Leaf-Crowned Elder @Wayne Reynolds
+1141 U Murasa Ranger @Eric Deschamps
+1142 R Nemata, Grove Guardian @John Avon
+1143 R Unstoppable Ash @Brian Snõddy
+1144 R Ancient Spider @Greg Staples
+1145 R Doomsday Specter @Donato Giancola
+1146 U Empyrean Eagle @Jason A. Engle
+1147 R Ghastlord of Fugue @Mike Dringenberg
+1148 R Gluttonous Troll @Joe Slucher
+1149 R Jared Carthalion, True Heir @Lius Lasahido
+1150 C Old Ghastbark @Thomas M. Baxa
+1151 R Tolsimir, Friend to Wolves @Ryan Pancoast
+1152 R Angelheart Vial @Chippy
+1153 R Dolmen Gate @Richard Sardinha
+1154 R Doom Cannon @Matthew Mitchell
+1155 R Eye of Doom @Yeong-Hao Han
+1156 R Forebear's Blade @Scott Murphy
+1157 R Jinxed Ring @M. W. Kaluta
+1158 R Rakdos Riteknife @Jim Nelson
+1159 M Ring of Three Wishes @Mark Winters
+1160 R Sword of Vengeance @Dan Scott
+1161 R Tower of Calamities @Aleksi Briclot
+1162 R Tower of Fortunes @Matt Cavotta
+1163 R Wheel of Torture @Henry Van Der Linde
+1164 U Forbidding Watchtower @Aleksi Briclot