Compare commits

...
Sign in to create a new pull request.

942 commits

Author SHA1 Message Date
d43ac44ada Merge pull request 'master' (#50) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 16m19s
Reviewed-on: #50
2025-11-30 14:36:26 -08:00
jmlundeen
9d9896bd4c convert transforming "E" cards to single class file 2025-11-28 22:35:31 -06:00
jmlundeen
bb69fe2595 convert transforming "D" cards to single class file 2025-11-28 12:59:54 -06:00
jmlundeen
a5d14f91f6 convert transforming "C" cards to single class file 2025-11-28 12:59:52 -06:00
jmlundeen
436ac5bbbd VerifyCardDataTest - update showCardInfo to check reference for both sides of the card 2025-11-28 12:59:49 -06:00
jmlundeen
97738afb9e revert card scanner changes 2025-11-28 12:59:48 -06:00
jmlundeen
0fc8d0871c convert transforming "B" cards to single class file 2025-11-28 12:59:36 -06:00
theelk801
f1d86a569f [TLA] Implement Koh, the Face Stealer 2025-11-28 13:41:52 -05:00
theelk801
bbb9a8f656 [TLE] Implement Tale of Katara and Toph 2025-11-28 10:47:52 -05:00
Grath
95f1e00fee [TLA] Fix Iroh, Grand Lotus
Was applying full-cost flashback to Lessons, which is not a benefit to anyone but should still be fixed.
2025-11-27 18:00:08 -05:00
jmlundeen
c5c42abb59 convert transforming "A" cards to single class file 2025-11-27 10:12:33 -06:00
jmlundeen
395a327cd3 fix verify 2025-11-27 09:42:47 -06:00
jmlundeen
b32a786236 add verify checks for Double Faced Cards having abilities on main card
* add booleans to card scanner, restricting to checking cards by name and set. Reduces duplication of verify checks across sets.
2025-11-27 09:39:46 -06:00
Jmlundeen
69e20b1061
Merge pull request #14061
* move setPT to Card

* Create DoubleFacedCard and DoubleFacedCardHalf to share code between …

* Create Transforming Double Face Card class

* allow putting either permanent side of a double faced card to the bat…

* refactor exile and return transforming card

* update ModalDoubleFacedCard references to DoubleFacedCard where relev…

* update for GUI

* refactor a disturb card

* refactor more disturb cards for test coverage

* refactor a transform card

* refactor more transform cards for test coverage

* fix Archangel Avacyn

* fix cantPlayTDFCBackSide inconsistency

* fix Double Faced Cards having triggers and static abilities when tran…

* fix Double Faced Cards card view erroring when flipping in client

* fix test_Copy_AsSpell_Backside inconsistency

* enable Spider-Man MDFC

* convert TDFC with saga as the front and add card references to Transf…

* refactor More Than Meets the Eye Card

* refactor a battle

* refactor a craft card

* update comment on PeterParkerTest

* Merge branch 'master' into rework-dfc

* fix Saga TDFC Azusa's Many Journeys

* fix double faced cards adding permanent triggers / effects to game

* move permanents entering map into Battlefield

* convert Room cards for new Permanent structure

* fix disturb not exiling

* Merge branch 'master' into rework-dfc

* fix Eddie Brock Power/Toughness

* fix Miles Morales ability on main card

* fix verify conditions for siege and day/night cards

* change room characteristics to text effect to match game rules

* update verify test to skip DoubleFacedCard in missing card test

* accidentally removed transform condition

* Merge branch 'master' into rework-dfc

* fix verify

* CardUtil - remove unnecessary line from castSingle method
2025-11-27 09:24:03 -06:00
theelk801
29557f4334 fix verify failure 2025-11-25 21:22:05 -05:00
theelk801
1700a06b00 [SLP] update and rename set 2025-11-25 21:06:56 -05:00
theelk801
b15e8b314a [TLE] Implement Fire Nation Salvagers 2025-11-25 19:52:11 -05:00
theelk801
a3dea879f0 [TLE] Implement Fire Lord Ozai 2025-11-25 19:42:58 -05:00
theelk801
210f93a7cc [TLA] fix Zuko, Conflicted not limiting modes 2025-11-25 18:57:42 -05:00
theelk801
1f21d6e716 [TLA] Implement Foggy Swamp Visions 2025-11-25 15:02:40 -05:00
theelk801
edbb5b0209 [TLA] Implement Hama, the Bloodbender 2025-11-25 14:55:18 -05:00
theelk801
10c5351b60 [TLE] Implement Nyla, Shirshu Sleuth 2025-11-25 12:56:52 -05:00
theelk801
54e23ac3f4 [TLE] Implement Storm of Memories 2025-11-25 12:42:35 -05:00
theelk801
9d46ecaf7f [TLE] Implement Momo's Heist 2025-11-25 12:37:47 -05:00
theelk801
bb0cc796f1 [TLE] Implement Waterbender's Restoration 2025-11-25 12:33:31 -05:00
theelk801
252707f947 [TLA] Implement Crashing Wave 2025-11-25 12:30:32 -05:00
theelk801
83e99022e1 [TLA] Implement Sandbender Scavengers 2025-11-25 12:23:37 -05:00
theelk801
04af8e94ab [TLA] Implement Obsessive Pursuit 2025-11-25 12:10:30 -05:00
theelk801
26488bf6e2 [TLA] Implement Zuko, Conflicted 2025-11-25 11:54:11 -05:00
Steven Knipe
bb5536b458 Fix Sokka and Sukki target 2025-11-24 18:08:42 -08:00
xenohedron
074f58d341
cleanup DamageTargetEffect (closes #11111) (#14096) 2025-11-23 01:00:34 -05:00
xenohedron
934d8e13f5 various text fixes 2025-11-22 20:44:33 -05:00
xenohedron
9c5e4b0698 fix The Destined Thief 2025-11-22 20:44:14 -05:00
xenohedron
153cac5587 fix Emptiness 2025-11-22 20:40:35 -05:00
xenohedron
d744b347f2 fix Bitterbloom Bearer token 2025-11-22 20:40:05 -05:00
xenohedron
4f8cc385fd fix Urban Retreat 2025-11-22 20:36:41 -05:00
xenohedron
d1b3dd3877 fix Iron Spider, Stark Upgrade 2025-11-22 20:31:37 -05:00
xenohedron
823ba6d849 fix Tectonic Split 2025-11-22 20:25:38 -05:00
xenohedron
3dfc836f14 fix Hermetic Herbalist 2025-11-22 20:23:20 -05:00
xenohedron
589a02ae85 fix verify 2025-11-22 20:17:57 -05:00
Grath
e8d5fb8c59 [TLA] Fix Earthbending with creature counter replacement
Did not work with effects that apply replacement effects to counters being added to creatures (but not to lands). Fixed by processing action between turning the land into a creature and putting the counters on it.
2025-11-21 11:47:15 -05:00
Grath
b715043d4a [FIN] Fix Summon: Brynhildr
1. Was looking for STUN counters being added rather than LORE counters.
2. Was not accounting for if Summon: Brynhildr was entering with a counter, such as on the first turn it was played.
2025-11-21 11:42:01 -05:00
Grath
b33ecac6bd Fix Cradle of Vitality. 2025-11-21 11:36:05 -05:00
theelk801
74305ee3fb [TLE] Implement Desperate Plea 2025-11-20 13:16:26 -05:00
theelk801
898e3a37d1 [TLE] Implement That's Rough Buddy 2025-11-20 13:11:22 -05:00
theelk801
36c6210cee [TLE] Implement Tale of Momo 2025-11-20 13:09:38 -05:00
theelk801
ebf82309fc [TLE] Implement Swampbenders 2025-11-20 12:57:39 -05:00
theelk801
e38c199177 fix verify failure again 2025-11-19 20:52:56 -05:00
theelk801
b8062c4131 fix verify failure 2025-11-19 20:32:35 -05:00
theelk801
440ece463a fix test failure 2025-11-19 19:50:10 -05:00
theelk801
6b4acfe5ce [TLA] Implement Jasmine Dragon Tea Shop 2025-11-19 16:00:17 -05:00
theelk801
4772658527 [TLA] Implement The Last Agni Kai 2025-11-19 13:19:11 -05:00
theelk801
80d58a35f7 [TLA] Implement The Earth King 2025-11-19 12:59:59 -05:00
theelk801
a656f0292a [TLA] Implement Trusty Boomerang 2025-11-19 12:46:35 -05:00
theelk801
85b5f91936 [TLE] fix Dutiful Knowledge Seeker ability 2025-11-19 12:32:23 -05:00
theelk801
832ebf0096 [TLE] Implement Wan Shi Tong, All-Knowing 2025-11-19 09:31:53 -05:00
theelk801
9b0f09ce91 [TLE] Implement Stand United 2025-11-19 09:25:28 -05:00
theelk801
6ba8c6fb90 [TLE] Implement Katara's Reversal 2025-11-19 09:11:05 -05:00
theelk801
3b978aa258 [TLE] Implement Hermitic Herbalist 2025-11-19 09:06:30 -05:00
theelk801
d6cc23ff95 [TLA] Implement Hermitic Herbalist 2025-11-19 08:55:54 -05:00
theelk801
7f06b7e3f7 [TLA] Implement White Lotus Hideout 2025-11-19 08:54:07 -05:00
theelk801
603ad33d0e [TLA] Implement Avatar Destiny 2025-11-19 08:50:47 -05:00
theelk801
e97718c6a8 [TLA] Implement Unlucky Cabbage Merchant 2025-11-19 08:30:06 -05:00
Steven Knipe
965bf8bea3 Fix Earthbend target for verify check 2025-11-18 23:01:41 -08:00
xenohedron
e7e6623ec9 fix #14079 (Fumble) 2025-11-18 22:47:01 -05:00
xenohedron
a2a4af7981 fix #14084 (The Darkness Crystal) 2025-11-18 22:41:47 -05:00
xenohedron
46452b252e verify fix 2025-11-18 21:14:39 -05:00
xenohedron
bc3240e94d some text fixes 2025-11-18 21:10:58 -05:00
xenohedron
4dcf37e007 fix text generation in new damage effect classes 2025-11-18 20:50:21 -05:00
xenohedron
2893fb43fc remove unneeded methods from DamageTargetEffect
minor cleanup to Sentinel Tower, Tephraderm

(see #11111)
2025-11-18 20:47:26 -05:00
xenohedron
aa1e2342e4 small fix Mournwillow 2025-11-18 20:47:26 -05:00
theelk801
426583ce83 [TLE] Implement Tectonic Split 2025-11-18 12:27:54 -05:00
theelk801
5bf14e2add [TLE] Implement Princess Yue 2025-11-18 11:55:25 -05:00
theelk801
07a1875561 [TLE] Implement Hog-Monkey Rampage 2025-11-18 11:46:53 -05:00
theelk801
1f0b829522 [TLE] Implement Hei Bai, Forest Guardian 2025-11-18 11:44:11 -05:00
theelk801
761818c90f [TLE] various text fixes 2025-11-18 11:30:24 -05:00
theelk801
790361f59f [TLA] various text fixes 2025-11-18 09:21:40 -05:00
theelk801
00c5daa5ea [TLA] Implement Ty Lee, Chi Blocker 2025-11-18 08:21:22 -05:00
theelk801
7aa91ab43e [TLA] Implement Toph, Hardheaded Teacher 2025-11-18 08:19:51 -05:00
theelk801
0ecd425069 [TLA] Implement Iroh, Tea Master 2025-11-18 08:15:02 -05:00
theelk801
f81b0645f5 [TLA] Implement Azula, Cunning Usurper 2025-11-18 07:59:12 -05:00
0171e2bbff Merge pull request 'master' (#49) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 17m0s
Reviewed-on: #49
2025-11-17 08:58:46 -08:00
theelk801
08a0fa285e [TLA] Implement The Blue Spirit 2025-11-17 09:38:59 -05:00
theelk801
aa2fd2534e [TLA] Implement Uncle's Musings 2025-11-17 09:31:56 -05:00
theelk801
f0370c4759 [TLA] Implement Sokka, Swordmaster 2025-11-17 09:27:49 -05:00
theelk801
0445d65777 [TLA] Implement Wartime Protestors 2025-11-17 09:17:19 -05:00
theelk801
9cfbcf6f84 [TLA] Implement Wan Shi Tong, Librarian 2025-11-17 09:14:56 -05:00
theelk801
31b682644a [TLE] Implement Katara, Seeking Revenge 2025-11-17 09:09:10 -05:00
theelk801
abb348ac1c [TLA] Implement Ruinous Waterbending 2025-11-17 09:05:33 -05:00
theelk801
5c8a185411 [TLA] Implement Spirit Water Revival 2025-11-17 09:00:58 -05:00
theelk801
1ae2ba93a7 [TLE] Implement The Duke, Rebel Sentry 2025-11-17 08:36:00 -05:00
theelk801
cb2e37c6a7 [TLE] Implement Reckless Blaze 2025-11-17 08:30:25 -05:00
theelk801
1abee5d86b [TLE] Implement Sokka and Suki 2025-11-17 08:20:11 -05:00
theelk801
f82f465c00 [UNF] add test for Embiggen 2025-11-17 08:10:50 -05:00
theelk801
6fbdc86ed8 [TLE] Implement Dutiful Knowledge Seeker 2025-11-16 17:31:41 -05:00
theelk801
3f0b37ea99 [TLA] Implement The Legend of Yangchen / Avatar Yangchen 2025-11-16 17:22:07 -05:00
theelk801
0c9ce259bd [TLA] Implement The Fire Nation Drill 2025-11-16 17:09:40 -05:00
theelk801
fad886d48b [TLA] Implement Team Avatar 2025-11-16 17:00:32 -05:00
theelk801
037e30f802 [TLA] Implement Honest Work 2025-11-16 16:56:47 -05:00
theelk801
b16fba2ceb [TLA] Implement The Legend of Kyoshi / Avatar Kyoshi 2025-11-15 10:38:02 -05:00
theelk801
886dd1f0b2 [TLA] Implement Lost Days 2025-11-15 10:24:28 -05:00
theelk801
7f85e6ef3f [TLA] Implement Combustion Man 2025-11-15 10:08:26 -05:00
theelk801
6b4b938713 [TLA] Implement Bumi, King of Three Trials 2025-11-15 10:03:06 -05:00
ReSech
49442b7caf
Slimefoot And Squee - fixed that it can't be activated without another target (#14089, #14088) 2025-11-15 13:10:31 +04:00
theelk801
25cd45c8b8 [TLE] Implement Toph, Greatest Earthbender 2025-11-14 15:58:20 -05:00
theelk801
be04d9b28f [TLE] Implement Suki, Kyoshi Captain 2025-11-14 15:55:22 -05:00
theelk801
a4adf6f844 [TLE] Implement Nightmares and Daydreams 2025-11-14 15:51:15 -05:00
theelk801
c193ff994b [TLE] Implement Monk Gyatso 2025-11-14 15:41:37 -05:00
theelk801
1447f467c3 [TLE] Implement Master's Guidance 2025-11-14 15:39:22 -05:00
theelk801
dc458681cc [TLE] Implement Lost in Memories 2025-11-14 15:35:54 -05:00
theelk801
ad61edd559 [TLE] Implement Kyoshi Warrior Exemplars 2025-11-14 15:30:52 -05:00
theelk801
6c45ec6004 [TLE] Implement Chong and Lily, Nomads 2025-11-14 15:30:39 -05:00
theelk801
7322bf784f [TLA] Implement Sparring Dummy 2025-11-14 15:13:55 -05:00
theelk801
2fd0065e7e [TLA] Implement Price of Freedom 2025-11-14 15:07:44 -05:00
theelk801
a59d57ae93 [TLA] Implement Phoenix Fleet Airship 2025-11-14 15:04:56 -05:00
theelk801
6b5fb2d4c2 [TLA] Implement Destined Confrontation 2025-11-14 14:56:57 -05:00
theelk801
4e2c4ec1f0 [TLE] Implement Lo and Li, Royal Advisors 2025-11-14 11:09:22 -05:00
theelk801
79afaa0fbb [TLE] Implement Hook Swords 2025-11-14 10:59:44 -05:00
theelk801
67dc571224 [TLE] Implement Giant Fly 2025-11-14 10:56:51 -05:00
theelk801
76605e2a9d [TLE] Implement Freedom Fighter Recruit 2025-11-14 10:56:03 -05:00
theelk801
80f604943d [TLE] Implement Elephant-Mandrill 2025-11-14 10:54:22 -05:00
theelk801
d10863b844 [TLE] Implement Bumi's Feast Lecture 2025-11-14 10:54:22 -05:00
theelk801
88fc3b9045 [TLE] Implement Appa the Vigilant 2025-11-14 10:54:22 -05:00
theelk801
b5954c90a5 [TLE] Implement Aang and Katara 2025-11-14 10:54:22 -05:00
theelk801
31b023a003 [TLA] Implement Raven Eagle 2025-11-14 10:32:19 -05:00
theelk801
70ffc77a5b [TLA] Implement Elemental Teachings 2025-11-14 10:27:59 -05:00
theelk801
7d482d7a44 [TLA] Implement The Legend of Roku / Avatar Roku 2025-11-14 10:03:02 -05:00
theelk801
cc330ac3b8 [TLA] Implement The Legend of Kurruk / Avatar Kurruk 2025-11-14 09:54:33 -05:00
4f714203ae Merge pull request 'master' (#48) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 18m43s
Reviewed-on: #48
2025-11-13 21:47:46 -08:00
Grath
5bfd0ae796 Syr Vondam's second ability needs to function from the graveyard and/or exile zones. 2025-11-13 16:21:40 -05:00
theelk801
62ad2a1545 [TLE] Implement Bosco, Just a Bear 2025-11-13 10:23:44 -05:00
theelk801
c76ffbb3f5 [TLE] Implement Bison Whistle 2025-11-13 10:20:13 -05:00
theelk801
3d4454c7da [TLE] Implement Baboon Spirit 2025-11-13 10:03:52 -05:00
theelk801
5c62f53b08 [TLE] Implement Air Nomad Student 2025-11-13 10:00:12 -05:00
theelk801
7a0142867a [TLA] Implement Iroh, Grand Lotus 2025-11-13 09:56:03 -05:00
theelk801
ab2980116d [TLA] Implement Fatal Fissure 2025-11-13 09:48:59 -05:00
theelk801
5ce393f617 [TLA] Implement Energybending 2025-11-13 09:44:59 -05:00
theelk801
998b737ab5 [TLA] Implement Earth Kingdom General 2025-11-13 09:35:04 -05:00
theelk801
09d3d89045 [TLA] Implement Avatar's Wrath 2025-11-13 09:28:13 -05:00
theelk801
694f5332cc [TLA] Implement Aang, Swift Savior / Aang and La, Ocean's Fury 2025-11-13 09:22:25 -05:00
theelk801
13f4a314a7 [TLA] Implement Allies at Last 2025-11-13 09:11:56 -05:00
theelk801
ee77746db8 [TLA] Implement Secret Tunnel 2025-11-13 09:08:50 -05:00
xenohedron
1cb72d0efb
Merge pull request #14078 from xenohedron/damagemulti
Rework effects that deal damage to multiple specific objects
2025-11-13 00:35:06 -05:00
theelk801
ac71e5d5d8 [TLA] Implement Vengeful Villagers 2025-11-12 10:53:02 -05:00
theelk801
d7b5c21894 [TLA] Implement Zhao, the Moon Slayer 2025-11-12 10:50:21 -05:00
theelk801
70444ba7de [TLA] Implement Waterbending Scroll 2025-11-12 10:41:23 -05:00
theelk801
74f7a4fcbe [TLA] Implement Waterbender Ascension 2025-11-12 10:37:58 -05:00
theelk801
3c3b6b4353 [TLA] Implement Walltop Sentries 2025-11-12 10:33:48 -05:00
theelk801
d63b816a5f [TLA] Implement Teo, Spirited Glider 2025-11-12 10:31:11 -05:00
theelk801
096795be00 [TLA] Implement Pirate Peddlers 2025-11-12 10:25:39 -05:00
theelk801
f5ce27f6c8 [TLA] Implement Messenger Hawk 2025-11-12 10:18:47 -05:00
theelk801
c0e10f0569 [TLA] Implement Lo and Li, Twin Tutors 2025-11-12 10:17:13 -05:00
theelk801
c602edeca3 [TLA] Implement Kyoshi Island Plaza 2025-11-12 10:10:03 -05:00
theelk801
6efb4e5df4 [TLA] Implement Foggy Swamp Spirit Keeper 2025-11-12 09:22:04 -05:00
theelk801
d83e1f1e4e [TLA] Implement Foggy Swamp Hunters 2025-11-12 09:21:11 -05:00
theelk801
473df7ac12 [TLA] Implement Fire Navy Trebuchet 2025-11-12 09:06:29 -05:00
theelk801
626317cf68 [TLA] Implement Ember Island Production 2025-11-12 09:01:52 -05:00
theelk801
4c3af32a50 [TLA] Implement Combustion Technique 2025-11-12 08:55:11 -05:00
theelk801
c76dd063f2 [TLA] Implement Beifong's Bounty Hunters 2025-11-12 08:52:03 -05:00
theelk801
e338f5c3f2 [TLA] Implement Aang, at the Crossroads / Aang, Destined Savior 2025-11-12 08:46:31 -05:00
theelk801
7bd6c157a8 [SLD] Implement Kratos, Stoic Father 2025-11-11 18:11:38 -05:00
theelk801
e6cb3fe68e [TLA] Implement Jet, Freedom Fighter 2025-11-11 18:11:38 -05:00
theelk801
b87735aa49 [TLA] Implement June, Bounty Hunter 2025-11-11 18:11:38 -05:00
theelk801
ad063f7874 [TLA] Implement Jeong Jeong, the Deserter 2025-11-11 18:11:37 -05:00
theelk801
e562c20f1d [TLA] Implement Earthen Ally 2025-11-11 18:11:37 -05:00
theelk801
d88f7c68d4 [TLA] Implement Day of Black Sun 2025-11-11 18:11:37 -05:00
theelk801
6cdc989c04 [TLA] Implement Bitter Work 2025-11-11 18:11:37 -05:00
theelk801
019e3ecf1c [TLA] Implement Boiling Rock Rioter 2025-11-11 18:11:37 -05:00
theelk801
4eaf1233c9 [TLA] Implement Realm of Koh 2025-11-11 18:11:37 -05:00
theelk801
522e54e215 [TLA] Implement Accumulate Wisdom 2025-11-11 18:11:37 -05:00
ReSech
6fc4a5fbba
Add TLA and TLE Tokens (#14083)
* Add copy tokens

* TLE Tokens

* Add TLA Tokens
2025-11-11 17:07:57 -06:00
theelk801
0ff60c91c1 fix test failure 2025-11-11 13:03:50 -05:00
theelk801
43e7d31cc5 [TLE] Implement Solid Ground 2025-11-11 12:47:03 -05:00
theelk801
697a914892 [TLE] Implement Scarring Memories 2025-11-11 12:45:23 -05:00
theelk801
c9af0467b9 [TLE] Implement Zuko, Seeking Honor 2025-11-11 12:41:47 -05:00
theelk801
9057461c29 [TLE] Implement Whirlwind Technique 2025-11-11 12:40:22 -05:00
theelk801
32d9c6887c [TLE] Implement Unagi's Spray 2025-11-11 12:38:06 -05:00
theelk801
47246ee381 [TLE] Implement Tui and La, Moon and Ocean 2025-11-11 12:35:34 -05:00
theelk801
9bdda9c5fd [TLE] Implement The Art of Tea 2025-11-11 12:32:36 -05:00
theelk801
654a29cba9 [TLE] Implement Sokka's Charge 2025-11-11 12:28:55 -05:00
theelk801
4c3a48b5f9 [TLE] Implement Smellerbee, Rebel Fighter 2025-11-11 12:24:30 -05:00
theelk801
6cd0c9d500 [TLE] Implement Ruthless Waterbender 2025-11-11 12:21:04 -05:00
theelk801
58206f24d5 [TLE] Implement Pipsqueak, Rebel Strongarm 2025-11-11 12:17:57 -05:00
theelk801
b412b9dd9a [TLE] Implement Overwhelming Victory 2025-11-11 12:15:55 -05:00
theelk801
04bd66b638 [TLE] Implement Moku, Meandering Drummer 2025-11-11 12:09:27 -05:00
theelk801
81592ac710 [TLE] Implement Mai and Zuko 2025-11-11 12:04:12 -05:00
theelk801
4742d414eb [TLE] Implement Longshot, Rebel Bowman 2025-11-11 12:02:17 -05:00
theelk801
defa5e20f5 [TLE] Implement Koala-Sheep 2025-11-11 11:40:11 -05:00
theelk801
ee99f7b094 [TLE] Implement Jet, Rebel Leader 2025-11-11 11:39:22 -05:00
theelk801
97f57fc0e0 [TLE] Implement Inspired Insurgent 2025-11-11 11:31:34 -05:00
theelk801
25e010ee01 [TLE] Implement Frantic Confrontation 2025-11-11 11:30:08 -05:00
theelk801
eafc6600da [TLE] Implement Founding of Omashu 2025-11-11 11:28:13 -05:00
theelk801
4cc7a079ec [TLE] Implement Fire Nation Turret 2025-11-11 11:26:05 -05:00
theelk801
d64e8b9194 [TLE] Implement Fire Nation Occupation 2025-11-11 11:23:23 -05:00
theelk801
f5802be133 [TLE] Implement Earthshape 2025-11-11 11:21:37 -05:00
theelk801
6fb84830b3 [TLE] Implement Deer-Dog 2025-11-11 11:13:45 -05:00
theelk801
bea75d55af [TLE] Implement Dai Li Censor 2025-11-11 11:13:24 -05:00
theelk801
8794545c9f [TLE] Implement Crystalline Armor 2025-11-11 11:12:08 -05:00
theelk801
7bb5e54eec [TLE] Implement Creeping Crystal Coating 2025-11-11 11:10:46 -05:00
theelk801
bfed992bf8 [TLE] Implement Cracked Earth Technique 2025-11-11 11:09:03 -05:00
theelk801
3bca2e4eab [TLE] Implement Chakra Meditation 2025-11-11 11:05:31 -05:00
theelk801
9d49f601c2 [TLE] Implement Aang, A Lot to Learn 2025-11-11 10:59:32 -05:00
xenohedron
f2bf831e61 improve verify checks for target tag usage 2025-11-11 00:20:32 -05:00
xenohedron
646d34a90e fix oversight for real this time 2025-11-10 22:35:55 -05:00
xenohedron
97fd15d7a6 fix oversight 2025-11-10 22:06:41 -05:00
theelk801
2799c3f1c0 update ban lists 2025-11-10 11:17:55 -05:00
xenohedron
71269f972e add failing tests using lifelink 2025-11-10 02:02:59 -05:00
xenohedron
1fb0d26db9 cleanup to common class 2025-11-10 02:01:58 -05:00
xenohedron
0ae2c2b86e remove custom multitarget handling from DamageTargetEffect 2025-11-10 01:53:27 -05:00
xenohedron
1a1f7ec588 update all cards that deal damage to two or more specific things simultaneously 2025-11-10 01:38:25 -05:00
xenohedron
b8394f99e2 new DamageTargetAndAllControlledEffect 2025-11-09 23:59:57 -05:00
xenohedron
03100a932e new DamageTargetAndTargetControllerEffect 2025-11-09 23:59:56 -05:00
xenohedron
24785b6d81 new DamageTargetAndSelfEffect 2025-11-09 23:59:56 -05:00
xenohedron
9f663f2a23 new DamageTargetAndYouEffect 2025-11-09 23:59:56 -05:00
xenohedron
7a6dfb7a2f new DamageTargetAndTargetEffect 2025-11-09 23:59:56 -05:00
xenohedron
06c51bd829 update to check damage batch by source 2025-11-09 23:59:55 -05:00
xenohedron
cd1f3985fd add test cases (not depending on lifelink) 2025-11-09 23:59:55 -05:00
xenohedron
f7855dda8b fix Awaken the Maelstrom 2025-11-09 20:55:51 -05:00
Steven Knipe
00ff663c40 implement Orcish Conscripts, rework can't block alone ability 2025-11-09 20:48:13 -05:00
Steven Knipe
d785193b97 implement Orcish Farmer 2025-11-09 20:48:13 -05:00
Steven Knipe
066fb6dd46 implement Sacred Boon and Scars of the Veteran 2025-11-09 20:48:13 -05:00
ssk97
f0e551dafb
Update damage prevention effects to use preventDamageAction (#14071) 2025-11-09 20:47:59 -05:00
xenohedron
caf7a2b8a9 fix verify 2025-11-09 20:47:27 -05:00
xenohedron
865b05781e fix Zuko's Conviction missing target 2025-11-09 14:26:06 -05:00
Grath
784bea734f Better fix with text generation. 2025-11-08 23:42:11 -05:00
ReSech
df20c64c58
Update reprints and tokens [SLC] [SLD] [PW25] [PSPL] (#14074)
* Add Mutagen Token

* Add missing SLC

* Add missing SLD

* Add missing PW25

* Add missing PSPL

* fix verify errors
2025-11-08 23:03:57 -05:00
Grath
86d0910e1e Update OptionalOneShotEffect with possibly better text generation. 2025-11-08 23:01:44 -05:00
ReSech
eb69df1623
FULL_ART Card and Check Fixes (#14004)
* Fix SLD Lands and SLC Full Art

* Update FULL_ART cards in SPM

* Update FULL_ART in SLD

* More SLD FULL_ART

* update test_checkWrongFullArtAndRetro
2025-11-08 15:26:13 -05:00
theelk801
70327c70c7 [TLA] Implement Zuko's Conviction 2025-11-08 15:24:22 -05:00
theelk801
f0d1fb8fa4 [TLA] Implement Water Tribe Rallier 2025-11-08 15:22:26 -05:00
theelk801
1bd3963079 [TLA] Implement Water Tribe Captain 2025-11-08 15:20:47 -05:00
theelk801
3c75bd4889 [TLA] Implement Wandering Musicians 2025-11-08 15:19:53 -05:00
theelk801
67004140ff [TLA] Implement South Pole Voyager 2025-11-08 15:19:15 -05:00
theelk801
a986cdf31e [TLA] Implement Rumble Arena 2025-11-08 15:16:10 -05:00
theelk801
cff73aa9f8 [TLA] Implement Meteor Sword 2025-11-08 15:13:47 -05:00
theelk801
6a2bc8f2ee [TLA] Implement Joo Dee, One of Many 2025-11-08 15:13:47 -05:00
theelk801
f744712d92 [TLA] Implement Foggy Swamp Vinebender 2025-11-08 15:13:47 -05:00
theelk801
da4c97acbe [TLA] Implement Firebending Lesson 2025-11-08 15:13:47 -05:00
theelk801
b69a4c1616 [TLA] Implement Earth Kingdom Protectors 2025-11-08 15:13:47 -05:00
theelk801
504d8d375f [TLA] Implement Curious Farm Animals 2025-11-08 15:13:47 -05:00
theelk801
71f642acc4 [TLA] Implement Canyon Crawler 2025-11-08 15:13:47 -05:00
theelk801
6a5fb5dd51 [TLA] Implement Boar-q-pine 2025-11-08 15:13:47 -05:00
theelk801
e996131ea9 [TLA] Implement Air Nomad Legacy 2025-11-08 15:13:47 -05:00
theelk801
401b70e616 [TLA] Implement Ba Sing Se 2025-11-08 15:13:46 -05:00
theelk801
7a71bf70aa [TLA] Implement Agna Qel'a 2025-11-08 15:13:46 -05:00
theelk801
80fdc8f88b [TLA] Implement Abandoned Air Temple 2025-11-08 15:13:46 -05:00
xenohedron
1c95a93af2 fix Carnage, Crimson Chaos (closes #14056) 2025-11-08 14:59:52 -05:00
xenohedron
a03e971090 fix Spider-Punk 2025-11-08 14:59:52 -05:00
xenohedron
8ac800b08b fix Shadow of the Goblin 2025-11-08 14:59:52 -05:00
xenohedron
39a8945589 fix Sandman, Shifting Scoundrel 2025-11-08 14:59:52 -05:00
xenohedron
d2559333e8 fix Koth of the Hammer 2025-11-08 14:59:52 -05:00
Tuomas-Matti Soikkeli
1327fe2b99
gui: cover scale style option for background images (#14049) 2025-11-08 14:59:45 -05:00
ReSech
7e34363954
Move cards from PMEI to LMAR and add missing PURL Reprints (#14008)
* Add new PURL reprints

* Move LMAR cards to dedicated set, remove from PMEI
2025-11-08 14:58:25 -05:00
ReSech
67660374cb Fix 2214 Back Image Download 2025-11-08 14:58:04 -05:00
ReSech
2b288cfd00 Add SLD Reprint and Tokens 2025-11-08 14:58:04 -05:00
theelk801
aac1aa55cc fix verify errors 2025-11-08 09:54:48 -05:00
theelk801
6e68121897 [TLE] update spoiler and reprints 2025-11-08 09:34:11 -05:00
theelk801
0d21b67057 [TLA] update spoiler 2025-11-08 09:33:53 -05:00
Grath
90815541f9 [TLA] Implement Ozai, the Phoenix King 2025-11-07 22:22:33 -05:00
Grath
a17635564a [TLE] Implement Iroh, Dragon of the West 2025-11-07 21:50:20 -05:00
Grath
3a92c32e48 [TLE] Implement Azula, Ruthless Firebender 2025-11-07 21:34:48 -05:00
Grath
b69fb2f4cd [TLE] Implement Zuko, Firebending Master 2025-11-07 20:48:57 -05:00
Grath
9c4bd210d7 [EOE] Fix Planetary Annihilation
It was never allowing people with 6 or fewer lands to save their lands.
2025-11-07 20:19:19 -05:00
Grath
a502ee94d5 [TLA] Implement Firebender Ascension
Also implemented an OptionalOneShotEffect for ease of stapling together a mandatory effect and an optional effect on the same ability.
2025-11-07 18:40:45 -05:00
Grath
4494bdddbb [TLA] Fix Fire Lord Azula. 2025-11-07 16:38:14 -05:00
Steven Knipe
93ebabf443 Fix IntPlusDynamicValue not modifying getMessage as well 2025-11-05 21:30:05 -08:00
Steven Knipe
d41d9693b4 Fix AzorsElocutors missing first ability 2025-11-05 21:25:19 -08:00
theelk801
cc9a7bafc3 [TLA] Implement Airbender's Reversal 2025-11-05 19:12:20 -05:00
theelk801
69c018fd3f [TLA] Implement The Walls of Ba Sing Se 2025-11-05 19:11:01 -05:00
theelk801
b77d6cd8fd [TLA] Implement Kyoshi Battle Fan 2025-11-05 19:10:01 -05:00
theelk801
fbf6fe6ae6 [TLA] update spoiler 2025-11-05 19:08:18 -05:00
theelk801
b05f749be4 [TLE] update spoiler and reprints 2025-11-05 19:07:58 -05:00
theelk801
e43cef514b [TLE] Implement Kindly Customer 2025-11-05 12:53:03 -05:00
theelk801
6e3d278fc8 [TLE] Implement Sokka's Sword Training 2025-11-05 12:52:23 -05:00
theelk801
52dbd96147 [TLE] Implement Toucan-Puffin 2025-11-05 12:51:23 -05:00
theelk801
49aab3a855 [TLE] update spoiler and reprints 2025-11-05 12:49:13 -05:00
theelk801
08130d98b1 fix verify failure 2025-11-05 12:42:35 -05:00
theelk801
1c56342485 [TLA] Implement Knowledge Seeker 2025-11-05 12:23:51 -05:00
theelk801
a50095e784 [TLA] Implement Wolfbat 2025-11-05 12:22:35 -05:00
theelk801
e4fcca82dd [TLA] Implement Benevolent River Spirit 2025-11-05 12:20:15 -05:00
theelk801
9c630578f1 [TLA] Implement Rockalanche 2025-11-05 12:19:24 -05:00
theelk801
6e0dc4f5f6 [TLA] Implement Professor Zei, Anthropologist 2025-11-05 12:17:45 -05:00
theelk801
835d4ae465 [TLA] Implement Great Divide Guide 2025-11-05 12:14:18 -05:00
theelk801
c9e4b33e4c [TLA] Implement Invasion Reinforcements 2025-11-05 12:12:00 -05:00
theelk801
d8b32308e8 [TLA] Implement Kyoshi Warriors 2025-11-05 12:11:20 -05:00
theelk801
35eeb2cb2d [TLA] Implement Swampsnare Trap 2025-11-05 12:10:10 -05:00
theelk801
9d1d27c9a5 [TLA] update spoiler 2025-11-05 12:08:16 -05:00
theelk801
d4635eb060 [TLA] Implement Sandbenders' Storm 2025-11-04 13:01:09 -05:00
theelk801
6b482f2afc [TLA] Implement Earthbender Ascension 2025-11-04 12:52:02 -05:00
theelk801
dc07b24ed3 [TLA] Implement Fire Nation Raider 2025-11-04 12:40:16 -05:00
theelk801
143efd64cb [TLA] update spoiler 2025-11-04 12:38:56 -05:00
theelk801
d968fb9f70 [TLA] Implement Boomerang Basics 2025-11-04 12:38:20 -05:00
theelk801
c3f359c5e8 [TLA] Implement Jet's Brainwashing 2025-11-04 10:08:03 -05:00
theelk801
dcf1ab14d7 [TLA] Implement Yip Yip! 2025-11-04 09:58:53 -05:00
theelk801
4c0270a5d5 [TLA] Implement Dai Li Agents 2025-11-04 09:53:44 -05:00
theelk801
34ddd612b3 [TLA] Implement Airbender Ascension 2025-11-04 09:45:00 -05:00
theelk801
ac7f33a156 [TLA] Implement Earth Rumble Wrestlers 2025-11-04 09:36:28 -05:00
theelk801
a13c339df2 [TLA] Implement Appa, Loyal Sky Bison 2025-11-04 09:27:28 -05:00
theelk801
ddb7e133c6 [TLA] Implement Sold Out 2025-11-04 09:27:28 -05:00
theelk801
f880a683f9 [TLA] Implement The Boulder, Ready to Rumble 2025-11-04 09:27:28 -05:00
theelk801
63b01b10d7 [TLE] Implement Iroh's Demonstration 2025-11-04 09:27:28 -05:00
theelk801
c473b7a189 [TLE] Implement Avatar Roku, Firebender 2025-11-04 09:27:28 -05:00
theelk801
f0ba075d56 [TLA] update spoiler 2025-11-04 09:27:18 -05:00
theelk801
6e5116b673 [TLA] Implement Enter the Avatar State 2025-11-04 08:47:08 -05:00
theelk801
da6ba92ba2 [TLA] Implement Earth Kingdom Jailer 2025-11-04 08:44:08 -05:00
theelk801
171ea63bc0 [TLA] Implement Cruel Administrator 2025-11-04 08:40:52 -05:00
theelk801
793c8d1daa [TLA] Implement Fire Nation Palace 2025-11-04 08:38:42 -05:00
theelk801
a0f0c0f6be [TLA] update spoiler 2025-11-04 08:33:54 -05:00
theelk801
10db510c35 [TLE] update spoiler and reprints 2025-11-04 08:33:38 -05:00
theelk801
0168db7a57 temporary verify fix 2025-11-03 20:30:22 -05:00
theelk801
269162bf32 [TLA] Implement Invasion Submersible 2025-11-03 19:54:16 -05:00
theelk801
64cde5ec17 [TLA] Implement Guru Pathik 2025-11-03 19:50:09 -05:00
theelk801
5ff8881d19 [TLA] Implement The Lion Turtle 2025-11-03 19:10:52 -05:00
theelk801
cbd6d11087 [TLA] Implement Earth King's Lieutenant 2025-11-03 19:04:48 -05:00
theelk801
1ec0897101 [TLA] Implement The Spirit Oasis 2025-11-03 19:00:18 -05:00
theelk801
777bb176bf [TLA] Implement Platypus-Bear 2025-11-03 18:52:34 -05:00
theelk801
6e0d6dfc36 [TLA] Implement Callous Inspector 2025-11-03 18:45:22 -05:00
theelk801
698f1d4668 [TLA] Implement The Unagi of Kyoshi Island 2025-11-03 18:41:42 -05:00
theelk801
a205bba849 [TLA] Implement Zhao, Ruthless Admiral 2025-11-03 18:39:43 -05:00
theelk801
ff79d9503e [SLC] update set 2025-11-03 18:38:02 -05:00
theelk801
48ee8eefc3 [TLE] update reprints 2025-11-03 18:37:25 -05:00
theelk801
5bf5bda8e5 [TLA] Implement Gather the White Lotus 2025-11-03 18:35:52 -05:00
theelk801
7caf775696 [TLA] Implement Tiger-Dillo 2025-11-03 18:32:36 -05:00
theelk801
3d6d30561d [TLA] Implement Twin Blades 2025-11-03 18:29:20 -05:00
theelk801
6a36947e65 [TLA] Implement Shared Roots 2025-11-03 18:27:23 -05:00
theelk801
08fc3bbdc1 [TLA] Implement Tolls of War 2025-11-03 18:26:37 -05:00
theelk801
44e6cf999e [TLA] Implement Mai, Scornful Striker 2025-11-03 18:24:31 -05:00
theelk801
0fc84fca38 [TLA] Implement Meditation Pools 2025-11-03 18:23:03 -05:00
theelk801
dfc91bf8cf [TLA] Implement Kyoshi Village 2025-11-03 18:22:53 -05:00
theelk801
19274aa8f0 [TLA] Implement Sun-Blessed Peak 2025-11-03 18:21:10 -05:00
theelk801
fffead4da5 [TLA] Implement Omashu City 2025-11-03 18:20:02 -05:00
theelk801
f4d4e80ed1 [TLA] Implement Foggy Bottom Swamp 2025-11-03 18:19:16 -05:00
theelk801
d2918e69f4 [TLA] Implement Boiling Rock Prison 2025-11-03 18:18:30 -05:00
theelk801
717baabdc3 [TLA] Implement Airship Engine Room 2025-11-03 18:17:30 -05:00
theelk801
46fa105b7e [TLA] Implement Serpent's Pass 2025-11-03 18:16:43 -05:00
theelk801
6766c7b45d [TLA] Implement Misty Palms Oasis 2025-11-03 18:15:35 -05:00
theelk801
76c6f4e2ec [TLA] Implement North Pole Gates 2025-11-03 18:14:43 -05:00
theelk801
852d1d4351 [TLA] update spoiler 2025-11-03 18:13:30 -05:00
Grath
ffb270eac7 [TLA] Implement Bumi, Unleashed 2025-11-02 17:58:37 -05:00
Grath
9ba96ddf11 Make Bebop and Rocksteady's discard optional. 2025-11-01 20:00:03 -04:00
Oleg Agafonov
a0bdfda912 cheats: fixed AI naming, improved cheat commands compatibility:
- added additional aliases for Human (me) and Computer (opponent, ai);
- now same cheat command will be work in real, test, duel or multiplayer games (Computer/Human);
- now same cheat command will be work in human only games;
- fixed wrong/random AI opponent selection in multiplayer games;
- fixed wrong opponent selection after first opponent's loose in multiplayer games;
2025-11-02 01:11:01 +04:00
Oleg Agafonov
064c102590 GUI, game: improved stack's hint with targets list (added player name and sorted by it); 2025-11-02 01:11:01 +04:00
theelk801
654dda8f74 [TLA] Implement Suki, Courageous Rescuer 2025-11-01 17:03:12 -04:00
theelk801
5e5b28151a [TLA] Implement Treetop Freedom Fighters 2025-11-01 17:00:19 -04:00
theelk801
621e7cd454 [TLA] Implement United Front 2025-11-01 16:59:32 -04:00
theelk801
639944d796 [TLA] Implement Mai, Jaded Edge 2025-11-01 16:58:11 -04:00
theelk801
b915d63787 [TLE] update reprints 2025-11-01 16:56:59 -04:00
theelk801
379cd5b7b7 [TLA] update spoiler 2025-11-01 16:56:29 -04:00
Steven Knipe
99bdfe3a1a Convert UnsealTheNecropolis and AnotherChance to use OneShotNonTargetEffect 2025-11-01 00:17:21 -07:00
theelk801
bcba45652f [TLA] Implement The Mechanist, Aerial Artisan 2025-10-31 12:33:46 -04:00
theelk801
d4b8c75619 [TLA] Implement Planetarium of Wan Shi Tong 2025-10-31 12:29:05 -04:00
theelk801
b7416356aa [TLA] Implement Northern Air Temple 2025-10-31 12:16:22 -04:00
theelk801
48fa39256e [TLA] Implement Origin of Metalbending 2025-10-31 12:01:37 -04:00
theelk801
0b796ea276 [TLA] Implement Toph, Earthbending Master 2025-10-31 09:15:10 -04:00
theelk801
55cc7dc36d [TLA] Implement Fire Nation Warship 2025-10-31 08:59:10 -04:00
theelk801
42a9cd8497 [TLA] Implement Fire Nation Cadets 2025-10-31 08:58:26 -04:00
theelk801
411eeab868 [TLA] Implement Bumi Bash 2025-10-31 08:53:36 -04:00
theelk801
c7fb5fd495 [TLA] Implement Octopus Form 2025-10-31 08:50:21 -04:00
theelk801
5d051f02ea [TLA] Implement Deadly Precision 2025-10-31 08:46:03 -04:00
theelk801
a19dbf129b [TLE] update spoiler and reprints 2025-10-31 08:44:29 -04:00
theelk801
531f2e3c38 [TLA] update spoiler 2025-10-31 08:44:11 -04:00
theelk801
8425601562 [TLA] Implement Diligent Zookeeper 2025-10-30 16:46:44 -04:00
theelk801
9f214bf0a3 [TLA] Implement Crescent Island Temple 2025-10-30 16:35:09 -04:00
theelk801
1551492939 [TLA] Implement Tundra Tank 2025-10-30 16:29:09 -04:00
theelk801
0e21b91fd3 [TLA] Implement Seismic Sense 2025-10-30 16:27:21 -04:00
theelk801
4b5b2e191e [TLA] Implement Glider Staff 2025-10-30 16:25:24 -04:00
theelk801
5c1c402fbf [TLA] Implement Fire Lord Azula 2025-10-30 16:23:43 -04:00
theelk801
75f26e3453 [TLA] Implement Dragonfly Swarm 2025-10-30 16:21:25 -04:00
theelk801
3ebe6ec782 [TLA] Implement Compassionate Healer 2025-10-30 16:16:38 -04:00
theelk801
4e46920b50 [TLA] Implement Sun Warriors 2025-10-30 13:26:38 -04:00
theelk801
2218ec0ae4 [TLA] Implement Uncle Iroh 2025-10-30 13:25:32 -04:00
theelk801
955fe40172 [TLA] Implement War Balloon 2025-10-30 13:24:14 -04:00
theelk801
87b040b86f [TLA] Implement Momo, Playful Pet 2025-10-30 13:21:53 -04:00
theelk801
ed34fa4061 [TLA] Implement Ty Lee, Artful Acrobat 2025-10-30 13:20:13 -04:00
theelk801
ba4c030009 [TLA] Implement Fancy Footwork 2025-10-30 13:18:33 -04:00
theelk801
fb4317a988 [TLA] Implement Forecasting Fortune Teller 2025-10-30 13:17:06 -04:00
theelk801
b1ca3804cc [TLA] Implement True Ancestry 2025-10-30 13:16:14 -04:00
theelk801
6db11cc000 [TLA] update spoiler 2025-10-30 13:14:35 -04:00
Grath
3c0593a7fa Update Duel Commander ban list. 2025-10-30 09:37:17 -04:00
jmlundeen
d98d59cc55 rework MayhemLandAbility to work properly 2025-10-29 21:00:11 -05:00
PurpleCrowbar
37ade28c31 Fix preference menu tooltip, minor preference menu clarity improvements 2025-10-29 20:29:49 +00:00
theelk801
13bf2126d3 fix error 2025-10-29 16:28:37 -04:00
theelk801
b489efa05c [TLE] update spoiler and reprints 2025-10-29 16:08:39 -04:00
dd34dc9b0b Merge pull request 'master' (#47) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 16m14s
Reviewed-on: #47
2025-10-29 13:07:39 -07:00
theelk801
4b3cacbf2b [TLA] Implement Sokka, Tenacious Tactician 2025-10-29 16:02:17 -04:00
theelk801
d3b0531777 [TLA] Implement Solstice Revelations 2025-10-29 15:59:43 -04:00
theelk801
9d2d7827ef [TLA] Implement Ran and Shaw 2025-10-29 15:49:21 -04:00
theelk801
3188c157df [TLA] Implement Leaves from the Vine 2025-10-29 15:40:40 -04:00
theelk801
8cd27af5a5 [TLA] Implement Invasion Tactics 2025-10-29 15:35:03 -04:00
theelk801
085fe11160 [TLA] Implement Cycle of Renewal 2025-10-29 15:31:48 -04:00
theelk801
459fe81ee4 [TLA] Implement Badgermole Cub 2025-10-29 15:29:40 -04:00
theelk801
9c799b432d [TLA] Implement Gran-Gran 2025-10-29 10:17:39 -04:00
theelk801
4ad97ef48c [TLA] Implement Avatar Kyoshi, Earthbender 2025-10-29 08:58:53 -04:00
theelk801
ac055bb808 [TLA] Implement The Cave of Two Lovers 2025-10-29 08:53:44 -04:00
theelk801
e47b17828b [TLA] Implement Zuko's Exile 2025-10-29 08:49:16 -04:00
theelk801
f5893a5c05 [TLA] Implement White Lotus Tile 2025-10-29 08:45:39 -04:00
theelk801
df68b4b4b1 [TLA] Implement White Lotus Reinforcements 2025-10-29 08:42:31 -04:00
theelk801
67dfb64b01 [TLA] Implement Tiger-Seal 2025-10-29 08:41:21 -04:00
theelk801
051440784f [TLA] Implement Sozin's Comet 2025-10-29 08:39:35 -04:00
theelk801
566bb511a6 [TLA] Implement North Pole Patrol 2025-10-29 08:38:09 -04:00
theelk801
a32a5caaa7 [TLA] Implement Firebending Student 2025-10-29 08:36:26 -04:00
theelk801
8778088016 [TLA] Implement Cunning Maneuver 2025-10-29 08:33:29 -04:00
theelk801
f43e0a72f4 [TLA] Implement Azula, On the Hunt 2025-10-29 08:31:59 -04:00
theelk801
774a3553fd [TLE] update spoiler and reprints 2025-10-29 08:24:23 -04:00
theelk801
0e589914de [TLA] update spoiler 2025-10-29 08:23:53 -04:00
xenohedron
09a423ae65 fix Aloy, Savior of Meridian ability 2025-10-26 19:02:34 -04:00
xenohedron
4bcb17a40e fix Devastating Onslaught number of token copies 2025-10-26 18:48:41 -04:00
xenohedron
6718c744e5 fix #14032 (Lizard, Connors's Curse) 2025-10-26 18:48:31 -04:00
xenohedron
313651cfc8 fix #14045 (Ultima, Origin of Oblivion)
rename method to correct typo
2025-10-26 18:33:13 -04:00
jmlundeen
ef4d48a654 Fix Knowledge Pool exile target 2025-10-26 16:25:45 -05:00
jmlundeen
5bbcda3d4e Update card test generation and card info templating
* now accepts lower case name matching
* partial matching also works with confirmation with multiple matches
2025-10-26 16:25:45 -05:00
jmlundeen
45e43fabd4 Fix Tandem Takedown damage target
fixes #14053
2025-10-26 12:57:22 -05:00
4065f20b2c fix typo
All checks were successful
/ build_release (push) Successful in 15m57s
2025-10-25 05:32:10 -07:00
eef561112e Merge pull request 'add lands to 3' (#46) from s3-lands into master
All checks were successful
/ build_release (push) Successful in 15m54s
Reviewed-on: #46
2025-10-25 01:17:11 -07:00
a142cc6abe add s3 lands 2025-10-25 01:15:47 -07:00
a713d8d584 Merge pull request 'add season 3' (#44) from season3 into master
All checks were successful
/ build_release (push) Successful in 15m59s
Reviewed-on: #44
2025-10-24 23:40:37 -07:00
ca9f3f3e1f Merge pull request 'master' (#45) from External/mage:master into season3
Reviewed-on: #45
2025-10-24 23:40:15 -07:00
1ad521d340 add season 3 2025-10-24 23:36:05 -07:00
PurpleCrowbar
b839c7bf87
Fix AI crashing server on too many target calculations. Closes #9539, #14031 (#14044) 2025-10-24 16:02:44 +01:00
Steven Knipe
4a458800aa Fix AerithRescueMission stunning all targets 2025-10-23 14:48:26 -07:00
Steven Knipe
b235e5e99d The Final Days' tokens should be tapped 2025-10-21 14:36:07 -07:00
Grath
496f147c15 Update brackets, label for "2-card combos" which are not stated as "infinite" in the bracket explainer chart. Fixes #14003 2025-10-21 14:19:06 -04:00
Grath
2092f3857e
Fix Saga first chapter ZCC
I've given JayDi enough opportunity to find his own fix, I'm merging this with a TODO to consider fixing it another way that JayDi's happy with.
2025-10-21 12:30:47 -04:00
Grath
9e475fccd1
Update AbilityImpl.java 2025-10-21 12:27:38 -04:00
PurpleCrowbar
b5118f2a5b Remove ward ability hint from Strong, the Brutish Thespian 2025-10-21 13:19:15 +01:00
Jeff Wadsworth
78281dbe69 A real fix for Glamer Spinners 2025-10-18 22:13:26 -05:00
PurpleCrowbar
94471f3126 [DSK] Implement Unholy Annex // Ritual Chamber 2025-10-17 21:17:00 +01:00
PurpleCrowbar
d63cfa56f8 [DSK] Implement Dollmaker's Shop // Porcelain Gallery 2025-10-17 20:28:16 +01:00
PurpleCrowbar
7e0fdcbe64 [DSK] Implement Dazzling Theater // Prop Room 2025-10-17 19:41:56 +01:00
PurpleCrowbar
cbf70893a8 [DSK] Implement Funeral Room // Awakening Hall 2025-10-17 19:25:16 +01:00
PurpleCrowbar
967e8e6bcb
[DSK] Implement Walk-In Closet // Forgotten Cellar (#14027) 2025-10-17 18:56:43 +01:00
oscscull
f7be842008
feature: implement Rooms (#13786)
- Adds Room + Room half card types
- Adds Room unlock ability
- Adds Room special functionality (locking halves, unlocking, changing names, changing mana values)
- Adjusts name predicate handling for Room name handling (Rooms have between 0 and 2 names on the battlefield depending on their state. They have 1 name on the stack as a normal split card does). Allows cards to match these names properly
- Adds Room game events (Unlock, Fully Unlock) and unlock triggers
- Updates Split card constructor to allow a single type line as with Rooms
- Adds empty name constant for fully unlocked rooms
- Updates Permanent to include the door unlock states (that all permanents have) that are relevant when a permanent is or becomes a Room.
- Updates ZonesHandler to properly move Room card parts onto and off of the battlefield.
- Updated Eerie ability to function properly with Rooms
- Implemented Bottomless Pool // Locker Room
- Implemented Surgical Suite // Hospital Room
- Added Room card tests
2025-10-16 01:36:31 -04:00
xenohedron
cb900eb799 fix Glamer Spinners, add test (fix #14022) 2025-10-16 01:07:21 -04:00
xenohedron
a8aef445fd dev: mark new script as executable 2025-10-16 00:57:31 -04:00
xenohedron
003fe945a2 fix Faller's Faithful 2025-10-16 00:45:02 -04:00
xenohedron
b8a65a31f4 fix filters on Bloodmark Mentor, Roughshod Mentor 2025-10-16 00:42:33 -04:00
PurpleCrowbar
98fbbb25b6 Remove menace hint from Agent Venom 2025-10-15 14:24:43 +01:00
Riley
4a41b0415a
Bugfixes for Kratos, God of War (#14001) 2025-10-14 18:53:31 -04:00
Steven Knipe
e8c8b72a07 Card fixes: MuYanlingCelestialWind "up to" target, RampagingGrowthEffect trying to put player onto battlefield instead of card 2025-10-12 20:14:23 -07:00
theelk801
8a3c6e1523 [TMC] Implement Donnie and April, Adorkable Duo 2025-10-12 10:02:03 -04:00
theelk801
3cf6da1735 [TMC] Implement Heroes in a Half Shell 2025-10-12 10:02:03 -04:00
theelk801
102b5b519d [TMC] Implement Raphael, the Muscle 2025-10-12 10:02:03 -04:00
theelk801
f012b18d8d [TMC] Implement Michelangelo, the Heart 2025-10-12 10:02:03 -04:00
theelk801
e9a115fca0 [TMC] Implement Leonardo, Worldly Warrior 2025-10-12 10:02:03 -04:00
theelk801
7cad86e90f [TMC] Implement Donatello, the Brains 2025-10-12 10:02:03 -04:00
jmlundeen
89f5e84ba7 Fix Electro, Assaulting Battery spell filter
closes #14010
2025-10-12 08:50:12 -05:00
theelk801
41c5076755 [TMC] Implement Splinter, the Mentor 2025-10-10 17:08:41 -04:00
theelk801
60addceff9 [TMC] Implement Donatello, Rad Scientist 2025-10-10 16:57:47 -04:00
theelk801
ad1866e4f0 [TMT] Implement April O'Neil, Hacktivist 2025-10-10 16:55:34 -04:00
theelk801
8bb8eba43d [TMT] Implement Krang, Master Mind 2025-10-10 16:47:23 -04:00
theelk801
747730568e [TMT] Implement Bebop & Rocksteady 2025-10-10 16:43:08 -04:00
theelk801
159933cc8a [TMT] Implement Raphael's Technique 2025-10-10 16:30:48 -04:00
theelk801
1c134ac2c2 fix verify error (the rest will be fixed once mtgjson updates) 2025-10-10 15:33:28 -04:00
theelk801
89c5b54d32 [TMC] Implement Leonardo, the Balance 2025-10-10 14:24:06 -04:00
theelk801
c2b22aba4a [TMT] Implement Super Shredder 2025-10-10 14:15:36 -04:00
theelk801
b9f003ab8c [TMT] Implement Casey Jones, Jury-Rig Justiciar 2025-10-10 14:13:46 -04:00
theelk801
891be73d87 [TMC] add set 2025-10-10 14:11:15 -04:00
theelk801
27f9105c9f [TMT] add set 2025-10-10 14:02:04 -04:00
theelk801
8375d6b606 rework partner variants, add tests 2025-10-10 13:56:39 -04:00
Steven Knipe
fec3599b73 Fix Spider Sense WebSlinging not have the target 2025-10-07 16:04:18 -07:00
theelk801
14fe52124c [FIC] Implement Mega Flare 2025-10-07 12:39:12 -04:00
theelk801
35bed32770 [FIC] Implement Vivi's Persistence 2025-10-07 12:32:17 -04:00
theelk801
085b450e62 [FIC] Implement Seifer, Balamb Rival 2025-10-07 12:28:34 -04:00
theelk801
b4cc09a7a0 [FIC] Implement Fishing Gear 2025-10-07 11:38:42 -04:00
31839c4eca Merge pull request 'master' (#43) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 14m39s
Reviewed-on: #43
2025-10-06 17:31:32 -07:00
Oleg Agafonov
4e29f4f241 version bump 2025-10-06 23:53:07 +04:00
Tuomas-Matti Soikkeli
d4ffa1e376
download: now new xmage install will save images as raw files instead zip archives for better compatibility on new systems (#13978) 2025-10-06 23:50:32 +04:00
ReSech
cbf47baf09
[MAR] added Marvel Universe Set with images (#13947)
* [SPM] Add Marvel Universe expansion set with initial card list

* Add support for Marvel Universe set in Scryfall image downloader

* Add "Wedding Ring" card to Marvel Universe expansion set

* Add MAR and SPM to GatherSets
2025-10-06 23:47:09 +04:00
ReSech
a098cb7849
dev: updated dependency versions of some libs (#13966)
batik-transcoder to 1.19
commons-compress to 1.28.0
gson to 2.13.2
commons-lang3 to 3.18.0
jsoup to 1.21.2
2025-10-06 23:45:24 +04:00
ReSech
911ab58fb9
images: added new reprints to SLD, PMEI and SLP (#13984)
* Add PMEI cards

* Add missing SLD cards

* Fix verify errors

* Add new SLP cards

* Add Cloud, Midgar Mercenary to PMEI

* tests: fixed verify test with miss booster

---------

Co-authored-by: Oleg Agafonov <jaydi85@gmail.com>
2025-10-06 23:44:03 +04:00
Oleg Agafonov
2884c898b3 deck: updated mtgo and paper cubes to the latest version; 2025-10-06 06:29:04 +04:00
Oleg Agafonov
9caa43dfac deck: updated infinite combos list for bracket levels 2025-10-06 05:37:52 +04:00
Oleg Agafonov
90bdec8f3d tests: fixed verify test with miss booster 2025-10-06 05:10:59 +04:00
theelk801
28409fefd4 [SLC] rename set 2025-10-02 13:40:43 -04:00
theelk801
df7187f09a [FIC] Implement Fated Clash 2025-10-02 12:33:01 -04:00
theelk801
2c97aa8688 [FIC] Implement Duelist's Flame 2025-10-02 12:27:04 -04:00
theelk801
dba03e67ee [FIC] Implement Campsite Cuisine 2025-10-02 09:40:55 -04:00
theelk801
8bae73cea3 [FIC] Implement Amarant Coral 2025-10-01 13:26:41 -04:00
theelk801
d6d75edf34 fix verify error 2025-10-01 10:54:16 -04:00
theelk801
d0ae249d93 fix compilation error 2025-10-01 10:33:40 -04:00
theelk801
d247df8515 [SLD] add latest drops 2025-10-01 10:10:41 -04:00
theelk801
b06039a437 [FIC] Implement Search for Dagger 2025-10-01 09:58:30 -04:00
theelk801
559690f15b [FIC] Implement Warrior's Resolve 2025-10-01 09:52:57 -04:00
theelk801
39d3b6995c [FIC] Implement The Destined Thief 2025-10-01 09:48:12 -04:00
theelk801
21f2ad43b7 [FIC] Implement Brilliant Wings 2025-10-01 09:37:31 -04:00
PurpleCrowbar
30ee9dc22f Remove ward ability hint from Valgavoth, Terror Eater 2025-10-01 13:40:34 +01:00
theelk801
f8e4defff8 fix verify failures 2025-09-30 21:21:56 -04:00
theelk801
b19adec4bc [FIC] Implement The Destined White Mage 2025-09-30 21:01:24 -04:00
theelk801
6ec4a2b781 [FIC] Implement The Destined Black Mage 2025-09-30 20:55:41 -04:00
theelk801
bbca3f342e [FIC] Implement Flash Photography 2025-09-30 20:52:13 -04:00
theelk801
7a3888e1ca [FIC] Implement The Destined Warrior 2025-09-30 20:49:08 -04:00
theelk801
ee149c9bdc [FIC] update spoiler and reprints 2025-09-30 20:43:47 -04:00
theelk801
9e464d3af1 [ECL] Implement Morningtide's Light 2025-09-30 12:01:48 -04:00
theelk801
e912e47640 [ECL] Implement Sygg, Wanderwine Wisdom / Sygg, Wanderbrine Shield 2025-09-30 11:57:41 -04:00
theelk801
68908db387 [ECL] Implement Eirdu, Carrier of Dawn / Isilu, Carrier of Twilight 2025-09-30 11:51:30 -04:00
theelk801
33ca328b38 [ECL] Implement Ashling's Command 2025-09-30 08:56:12 -04:00
theelk801
29ab28fd74 [ECL] Implement Figure of Fable 2025-09-30 08:51:01 -04:00
theelk801
265fbcfe82 [ECL] Implement Formidable Speaker 2025-09-30 08:38:37 -04:00
theelk801
db8b2927a7 [FIN] add newest printings 2025-09-30 08:33:40 -04:00
theelk801
2a81886bc7 [ECL] Implement Deceit 2025-09-29 11:52:04 -04:00
theelk801
1498dded50 [ECL] Implement Emptiness 2025-09-29 11:49:38 -04:00
theelk801
d46a258044 [SLD] Implement Ellie, Brick Master 2025-09-29 11:34:07 -04:00
theelk801
dba77b9858 [SLD] Implement Aloy, Savior of Meridian 2025-09-29 11:33:58 -04:00
theelk801
4a81ca7c78 [SLD] Implement Abby, Merciless Soldier 2025-09-29 11:14:03 -04:00
theelk801
8749dcc2d4 [SLD] Implement Kratos, God of War 2025-09-29 09:33:57 -04:00
theelk801
8bdf3378dc [SLD] update spoiler 2025-09-29 09:25:31 -04:00
theelk801
5f6c8a6faf [SLD] update file with latest new cards 2025-09-28 19:49:04 -04:00
theelk801
a695de10ee [SLD] update spoiler 2025-09-28 19:48:49 -04:00
theelk801
11f7e6347a [SLD] Implement Joel, Resolute Survivor 2025-09-28 19:46:01 -04:00
theelk801
7c114272d7 [SLD] Implement Ellie, Vengeful Hunter 2025-09-28 19:43:28 -04:00
theelk801
7b131673be [SLD] Implement Atreus, Impulsive Son 2025-09-28 19:39:48 -04:00
theelk801
1c0525d058 fix verify failure 2025-09-28 19:32:41 -04:00
theelk801
3ca0101495 [SLD] Implement Jaws, Relentless Predator 2025-09-28 19:31:26 -04:00
theelk801
dd316ee61f [ECL] Implement Mutable Explorer 2025-09-28 19:11:23 -04:00
theelk801
454c7e0116 [ECL] Implement Bitterbloom Bearer 2025-09-28 18:59:41 -04:00
theelk801
d7dec3baa5 [ECL] add set 2025-09-28 18:56:58 -04:00
ssk97
8cd1bec19d
Bestow rework/fixes (#13973)
* New Bestow test, minor improvements

* Partially rework Bestow to not rely on perpetual card modifications

* Add Bestow subtype tests, improve PrototypeTest

* Fix Subtype existing without required card type

* Improve docs, improve aura spell copy target copying check, improve subtype handling

* Add additional test

* Review improvements

* Remove subtype/type check

* Consolidate temporary becomeAura into function

* Add Enchant Creature ability
2025-09-27 23:57:31 -07:00
d44ecab868 Merge pull request 'master' (#42) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 18m27s
Reviewed-on: #42
2025-09-26 15:25:25 -07:00
Steven Knipe
95f53fc671 Fix BeholdTheSinisterSixTarget counting everything as illegal 2025-09-25 20:13:54 -07:00
ReSech
d95f77d352
[SLD] Add Play-Doh: Squishful Thinking reprints (#13974) 2025-09-23 00:28:05 -04:00
xenohedron
fba06baf3c fix Evolved Spinoderm 2025-09-23 00:26:15 -04:00
Miquel
807f69f548
[BOT] Implement Cyclonus, the Saboteur (#13963) 2025-09-22 22:42:54 -04:00
Steven Knipe
db823de8cd Fix ArachnePsionicWeaver incorrectly targeting 2025-09-21 20:17:05 -07:00
Steven Knipe
23f32bcd61 Fix nondeterministic testBlinkSoulStone 2025-09-21 19:49:26 -07:00
Steven Knipe
355a0972c0 Fix Pestilence 2025-09-20 14:50:40 -07:00
Steven Knipe
aa6c97f8f2 Fix Pyrohemia, add note in docs about default "onlyControlled" behavior 2025-09-20 05:10:04 -07:00
a240168e52 Merge pull request 'master' (#41) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 17m40s
Reviewed-on: #41
2025-09-19 20:24:36 -07:00
3f29618d03 add YMKM + Emporium Thopterist
Some checks failed
/ build_release (push) Has been cancelled
2025-09-19 20:22:49 -07:00
PurpleCrowbar
287afad212 Minor text and code cleanup for Spellskite 2025-09-18 19:07:27 +01:00
theelk801
14c41875df [SPM] update set file 2025-09-18 13:02:47 -04:00
theelk801
11ff92e3cc fix verify failure 2025-09-18 12:58:03 -04:00
Jmlundeen
d886da6e52
[SPM] Implement The Soul Stone (#13936)
* [SPM] Implement The Soul Stone

* update to use permanent designation instead of game state

* update The Soul Stone according to release notes

* infinity ability is no longer on the card unless harnessed, which is only on the battlefield

* fix text on soul stone conditional ability

* update The Soul Stone

* create common effects for future Infinity cards
2025-09-18 12:56:17 -04:00
466f6ed385 Merge pull request 'master' (#40) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 21m46s
Reviewed-on: #40
2025-09-18 08:48:02 -07:00
xenohedron
ef7a511f0c fix Jodah's Avenger and Argivian Avenger
(regression from #12619, like #13215)
2025-09-18 00:26:12 -04:00
Steven Knipe
bba214c1f8 Fix SandstalkerMoloch not resetting watcher 2025-09-16 14:21:51 -07:00
Steven Knipe
078e702a75 Fix CallToTheGrave comparison 2025-09-16 14:13:05 -07:00
Steven Knipe
4229d7fb13 AuramancersGuise use AttachedToAttachedPredicate 2025-09-13 20:05:16 -07:00
Steven Knipe
ff5e7f2d16 Use AttachedToAttachedPredicate from 49a3b11 for GolemSkinGauntlets and BrassKnuckles, improve GolemSkinGauntletsTest 2025-09-13 17:59:29 -07:00
xenohedron
49d65c1a88 more text fixes 2025-09-13 20:06:08 -04:00
xenohedron
18a050fb70 general text gen fixes 2025-09-13 19:47:29 -04:00
xenohedron
9a6504c1fa fix some card text 2025-09-13 19:47:29 -04:00
xenohedron
10a8059eae fix trigger to be optional 2025-09-13 19:47:28 -04:00
xenohedron
95c326b200 revert erroneous rework from bbbc2e5b 2025-09-13 19:47:28 -04:00
xenohedron
4ce2e561fb fix filter 2025-09-13 19:47:28 -04:00
xenohedron
35e906513c fix regression from refactor in 49a3b117 2025-09-13 19:47:28 -04:00
xenohedron
4d5971c946 fix missing ability (regression from f024e3b0) 2025-09-13 19:47:28 -04:00
xenohedron
7a4c82cd52 errata: Rampaging Baloths trigger no longer optional 2025-09-13 18:53:55 -04:00
xenohedron
8056dd3887 fix Thundermane Dragon predicate 2025-09-13 18:07:25 -04:00
Evan Kranzler
652ca6c9e1
[FIN] Implement Summon: Brynhildr (#13699)
* [FIN] Implement Summon: Brynhildr

* cleanup of common classes and constructors

---------

Co-authored-by: xenohedron <12538125+xenohedron@users.noreply.github.com>
2025-09-12 18:28:09 -04:00
Grath
6d0dc2f0df [SPM] You need to include the zone so that Morbius can get into Morbin' Time. 2025-09-12 17:52:03 -04:00
xenohedron
03679f84fe Revert "Use raw images instead of zip files to reduce errors. (#13588)"
This reverts commit 5f22d4e5cd.
2025-09-12 17:10:34 -04:00
padfoothelix
b41a4872a5
[WHO] Implement The Fourth Doctor (#13731)
* Implement The Fourth Doctor

* Fix triggered ability

* Change hint and PlayFromTop effect in The Fourth Doctor

* null check

* whitespace fix

---------

Co-authored-by: xenohedron <xenohedron@users.noreply.github.com>
2025-09-12 17:07:17 -04:00
xenohedron
34c26f09c8
refactor methods to find cards in exile (#13967)
* refactor exile method names, add comments

* fix card effects checking exile with filter to process ObjectSourcePlayerPredicates

* fix card effects checking exile to respect range of influence
2025-09-12 17:06:53 -04:00
ReSech
32af4a0671
Fix card numbers for failing downloads (#13962) 2025-09-12 17:06:36 -04:00
PurpleCrowbar
6b7a757c2f Fix Maarika showing all enemy untapped, noncreature permanents as being required to block her
Now only creatures get the "Must block Maarika" hint in their tooltip on mouseover
2025-09-09 17:38:43 +01:00
PurpleCrowbar
c03f3502df Fix Cultivate (and like cards) effect prompt text 2025-09-09 17:32:43 +01:00
PurpleCrowbar
bf6a7684d6 Fix Urza, Chief Artificer 2025-09-09 12:36:56 +01:00
ReSech
441ea0fa89
Frame fixes (#13960)
* Update card entries to use FULL_ART_USE_VARIOUS

* Add additional cards
2025-09-08 13:45:15 -05:00
PurpleCrowbar
38c0cc973d Fix Warp ability's exile zone name 2025-09-08 15:07:33 +01:00
ReSech
7e7b519f49
Add tokens from TSPM (#13958) 2025-09-07 19:41:16 -05:00
jmlundeen
c7a79197e5 [SPM] update News Helicopter and Spider-Girl to use HumanCitizenToken 2025-09-07 19:36:25 -05:00
Tuomas-Matti Soikkeli
5f22d4e5cd
Use raw images instead of zip files to reduce errors. (#13588) 2025-09-07 17:52:00 -04:00
Thorsten Hacke
41b8f57883
fix Shared Fate to respect range of influence correctly (#13839)
* change opponents filter to check oponents of drawing player instead of cards controller

* check for player and controller range
2025-09-07 17:51:16 -04:00
Jmlundeen
4dd7e963bc
update RemoveCountersSourceCost, Gwen Stacy, and Price of Betrayal (#13941)
* update RemoveCountersSourceCost, Gwen Stacy, and Price of Betrayal

* added support for choosing multiple counters to RemoveCountersSourceCost

* changed Price of Betrayal to use player.getMultiAmount method

* added REMOVE_COUNTERS to MultiAmountType

* create common RemoveUpToAmountCountersEffect and update cards

* update default target wording on RemoveUpToAmountCountersEffect
2025-09-07 17:50:46 -04:00
Jmlundeen
432de6f9fe
[SPM] implement Terrific Team-Up and create a shared effect (#13954)
* create common TargetsDamageTargetsEffect

* [SPM] implement Superior Terrific Team-Up

* fix band together second target predicate

* remove unnecessary checks in TargetsDamageTargetsEffect
2025-09-07 17:50:34 -04:00
Jmlundeen
d2a7991f8e
[SPM] implement The Death of Gwen Stacy and update ExileGraveyardTargetPlayerEffect (#13955)
* refactor ExileGraveyardAllTargetPlayerEffect to allow multiple targets

* [SPM] implement The Death of Gwen Stacy

* change ExileGraveyardAllTargetPlayerEffect to do one batch movement
2025-09-07 17:50:21 -04:00
ReSech
d46ccdd8bc
[SLD] add reprints (#13948)
* Add Daily Bugle Breaking News

* Fix verify errors
2025-09-07 00:38:18 -04:00
xenohedron
0b4d8d02d7 fix Stone Idol Trap and Esper Terra 2025-09-07 00:36:08 -04:00
xenohedron
f92af2b9cd refactor: consistent logic for delayed triggers that sacrifice/exile tokens
single trigger for multiple tokens
2025-09-07 00:36:08 -04:00
xenohedron
457a5303f3 fix Mardu Siegebreaker 2025-09-07 00:36:08 -04:00
xenohedron
199652463c fix Pia Nalaar, Chief Mechanic 2025-09-07 00:36:08 -04:00
xenohedron
53382bd6c9 fix Virulent Silencer 2025-09-07 00:36:08 -04:00
xenohedron
2cd89bb2db gui, client: reduce grid padding for better screen space usage 2025-09-07 00:36:08 -04:00
jmlundeen
8f1050a834 [SPM] implement The Spot, Living Portal 2025-09-06 22:34:30 -05:00
Grath
d0ee2fef06 [FIN] Golbez returns card to hand, not battlefield - can't getPermanent on a Card. 2025-09-06 11:38:07 -04:00
jmlundeen
4dd5054314 [SPM] fix Superior Spider-Man reflexive trigger 2025-09-06 07:30:17 -05:00
theelk801
401e09830d fix verify failures 2025-09-05 21:01:40 -04:00
jmlundeen
f7c239c1fe [SPM] implement Superior Spider-Man 2025-09-05 17:15:47 -05:00
jmlundeen
3fc3b9da1a [SPM] implement Superior Foes of Spider-Man 2025-09-05 17:15:47 -05:00
jmlundeen
3ac86997b2 create common ExileTopCardPlayUntilExileAnotherEffect 2025-09-05 17:15:47 -05:00
jmlundeen
2e70279485 [SPM] implement Strength of Will 2025-09-05 17:15:47 -05:00
jmlundeen
d5a0a139a5 [SPM] implement Web-Shooters 2025-09-05 17:15:47 -05:00
theelk801
7df3985dd9 [SPM] Implement Villainous Wrath 2025-09-05 18:15:01 -04:00
theelk801
988c661ccf [SPM] Implement Wall Crawl 2025-09-05 18:10:01 -04:00
theelk801
7df7286a27 [SPM] Implement The Spot's Portal 2025-09-05 18:05:15 -04:00
theelk801
1fc6abc08e [SPM] Implement Wisecrack 2025-09-05 14:43:11 -04:00
theelk801
2a39c13f4a [SPM] Implement Sudden Strike 2025-09-05 14:39:05 -04:00
jmlundeen
59b4a5d766 [SPM] unimplemented card in set 2025-09-05 13:32:02 -05:00
jmlundeen
54975d8051 [SPM] update wrong effect access levels 2025-09-05 13:28:54 -05:00
jmlundeen
721b9b90c9 [SPM] update Mister Negative name and text 2025-09-05 13:28:51 -05:00
jmlundeen
2f15477214 [SPM] implement Spider-Verse 2025-09-05 13:27:43 -05:00
jmlundeen
32282a42b7 [SPM] implement Spider-Slayer, Hatred Honed 2025-09-05 13:27:43 -05:00
jmlundeen
388635140f [SPM] implement Spider-Mobile 2025-09-05 13:27:43 -05:00
jmlundeen
50e0d200cb [SPM] implement Spider-Man No More 2025-09-05 13:27:43 -05:00
jmlundeen
7539ba7a4f [SPM] implement Silk, Web Weaver 2025-09-05 13:27:43 -05:00
jmlundeen
bd769d651e [SPM] implement Shriek, Treblemaker 2025-09-05 13:27:43 -05:00
theelk801
9092518aa9 small extra fix 2025-09-05 14:21:52 -04:00
theelk801
33852c72e7 fix test failure 2025-09-05 14:21:35 -04:00
theelk801
76708eaa9f [SPM] Implement Hobgoblin, Mantled Marauder 2025-09-05 14:04:52 -04:00
theelk801
595e40850c [SPM] Implement Savage Mansion 2025-09-05 14:03:54 -04:00
theelk801
5e0b79d021 [SPM] Implement Sinister Hideout 2025-09-05 14:03:00 -04:00
theelk801
c485d70dcf [SPM] update spoiler 2025-09-05 14:01:19 -04:00
jmlundeen
b63660e022 [SPM] implement Shadow of the Goblin 2025-09-05 10:57:26 -05:00
jmlundeen
f663f5e002 [SPM] implement Secret Identity 2025-09-05 10:20:51 -05:00
jmlundeen
d5fa369e4d [SPM] implement Mr. Negative 2025-09-05 10:08:04 -05:00
jmlundeen
fec244c675 [SPM] implement Morlun, Devourer of Spiders 2025-09-05 08:32:13 -05:00
jmlundeen
91d67ba81b [SPM] implement Morbius the Living Vampire 2025-09-04 22:42:55 -05:00
jmlundeen
73205c4be2 [SPM] implement Alien Symbiosis 2025-09-04 22:42:55 -05:00
jmlundeen
54a8e8ef31 [SPM] implement Maximum Carnage 2025-09-04 15:35:20 -05:00
jmlundeen
2fb8a97e6a [SPM] implement Jackal, Genius Geneticist 2025-09-04 15:35:20 -05:00
jmlundeen
d1b11cad4f [SPM] implement Biorganic Carapace 2025-09-04 15:35:20 -05:00
jmlundeen
37cffc3895 [SPM] implement Arachne, Psionic Weaver 2025-09-04 15:35:20 -05:00
jmlundeen
ed134cbfc6 [SPM] implement Scarlet Spider, Ben Reilly 2025-09-04 15:35:19 -05:00
jmlundeen
8b6b90c8d8 [SPM] implement Rhino's Rampage 2025-09-04 15:35:19 -05:00
jmlundeen
43d315861d [SPM] implement Sandman's Quicksand 2025-09-04 15:35:19 -05:00
theelk801
411e25661a [SPM] Implement Spider-Girl, Legacy Hero 2025-09-04 16:10:55 -04:00
theelk801
4cac317907 [SPM] Implement Silver Sable, Mercenary Leader 2025-09-04 16:08:27 -04:00
theelk801
52a2165697 [SPM] Implement Sun-Spider, Nimble Webber 2025-09-04 16:06:24 -04:00
theelk801
cf34f859b7 [SPM] Implement Urban Retreat 2025-09-04 16:04:19 -04:00
theelk801
d60bd053fa [SPM] update spoiler 2025-09-04 15:59:48 -04:00
theelk801
823d80bf0d [SPM] Implement University Campus 2025-09-04 12:02:04 -04:00
theelk801
9ca98bb108 [SPM] Implement Mysterio's Phantasm 2025-09-04 11:59:59 -04:00
theelk801
2144d76895 [SPM] update spoiler 2025-09-04 11:58:09 -04:00
theelk801
7f4759f708 [SPM] Implement Venomized Cat 2025-09-04 09:08:16 -04:00
theelk801
6c45e5606a [SPM] Implement Subway Train 2025-09-04 09:05:33 -04:00
theelk801
84526973d9 remove unnecessary TargetTriggeredAbility class 2025-09-04 09:05:21 -04:00
theelk801
c091795a97 [SPM] Implement Spider-Sense 2025-09-04 09:05:21 -04:00
theelk801
30ca433785 [SPM] Implement Robotics Mastery 2025-09-04 09:05:21 -04:00
theelk801
fe005e9477 [SPM] Implement Doc Ock's Tentacles 2025-09-04 09:05:03 -04:00
jmlundeen
c952311df0 [SPM] implement Passenger Ferry 2025-09-04 07:57:11 -05:00
jmlundeen
0df165604b [SPM] implement Living Brain, Mechanical Marvel 2025-09-04 07:41:39 -05:00
jmlundeen
1fe8097307 [SPM] implement Hide on the Ceiling 2025-09-04 07:10:33 -05:00
jmlundeen
d37ee2edc4 [SPM] implement Amazing Acrobatics 2025-09-03 22:11:12 -05:00
jmlundeen
fb4303fbe6 [SPM] fix Oscorp Industries test 2025-09-03 22:04:45 -05:00
jmlundeen
d5b496c7f1 [SPM] update spoiler 2025-09-03 21:03:42 -05:00
jmlundeen
0b5638fbae [SPM] Implement Parker Luck 2025-09-03 20:59:42 -05:00
jmlundeen
0f1c19900c [SPM] Lizard, Connors's Curse 2025-09-03 20:59:42 -05:00
jmlundeen
9e60c50771 [SPM] Cheering Crowd 2025-09-03 20:59:42 -05:00
jmlundeen
34cf4617f0 [SPM] Implement Molten Man, Incarnation of Hellfire 2025-09-03 20:59:42 -05:00
jmlundeen
502b08762f [SPM] Implement Madame Web, Clairvoyant 2025-09-03 20:59:42 -05:00
jmlundeen
5bbeb9391f [SPM] Implement Inner Demons Gangsters 2025-09-03 20:59:42 -05:00
jmlundeen
4b8b1a95ad [SPM] Implement Hydro-Man, Fluid Felon 2025-09-03 20:59:42 -05:00
jmlundeen
00180cffa6 [SPM] Implement Heroe's Hangout 2025-09-03 20:59:42 -05:00
jmlundeen
538debf2e0 [SPM] Implement Black Cat, Cunning Thief 2025-09-03 20:59:42 -05:00
jmlundeen
6e29b8e7fa [SPM] Implement Oscorp Industries 2025-09-03 20:59:42 -05:00
jmlundeen
e19c454aa3 [SPM] Implement Interdimensional Web Watch 2025-09-03 20:59:42 -05:00
jmlundeen
e7636fb17d [SPM] Implement Lady Octopus, Inspired Inventor 2025-09-03 20:59:42 -05:00
jmlundeen
5bb8ff2c7f [SPM] Implement Friendly Neighborhood 2025-09-03 20:59:42 -05:00
jmlundeen
ace21c67c1 add withQuotes chaining method to GainAbilityAttachedEffect 2025-09-03 20:59:42 -05:00
jmlundeen
a740a2b2dc [DSK] fix Unidentified Hovership 2025-09-03 20:59:42 -05:00
Steven Knipe
06543904f2 SatyrFiredancer's Effect and TargetAdjuster can be generic 2025-09-03 17:31:45 -07:00
Steven Knipe
9aafd4a14e Fix Skyserpent Seeker moving 1st land back into library 2025-09-03 17:17:06 -07:00
theelk801
95b8fc92ef [SPM] Implement Mary Jane Watson 2025-09-03 17:50:46 -04:00
theelk801
f919c56da7 [SPM] Implement Swarm, Being of Bees 2025-09-03 17:49:14 -04:00
theelk801
4bfa4c82a6 [SPM] update spoiler 2025-09-03 17:47:51 -04:00
theelk801
971f83b19c [SPM] Implement Bagel and Schmear 2025-09-03 14:41:15 -04:00
theelk801
f7e1f1d346 [SPM] Implement Mob Lookout 2025-09-03 14:36:58 -04:00
theelk801
a95f6f88d5 [SPM] Implement Spider-Woman, Stunning Savior 2025-09-03 14:35:53 -04:00
theelk801
2db53973f9 [SPM] Implement Wraith, Vicious Vigilante 2025-09-03 14:34:06 -04:00
theelk801
1b345c58ac [SPM] Implement Spider Manifestation 2025-09-03 14:33:14 -04:00
theelk801
0cb3646960 [SPM] update spoiler 2025-09-03 14:30:16 -04:00
theelk801
b3fc051a3d [SPM] Implement Vibrant Cityscape 2025-09-03 14:28:33 -04:00
theelk801
f2700a5448 [SPM] Implement Suburban Sanctuary 2025-09-03 14:27:34 -04:00
theelk801
7681433faf [SPM] Implement News Helicopter 2025-09-03 14:26:21 -04:00
theelk801
e94ff0949f [SPM] Implement Hot Dog Cart 2025-09-03 14:25:34 -04:00
theelk801
02ccf58bdd [SPM] Implement Gallant Citizen 2025-09-03 14:24:32 -04:00
theelk801
3062be1e44 [SPM] Implement Kraven, Proud Predator 2025-09-03 14:23:45 -04:00
theelk801
2c2e37e792 [SPM] Implement Professional Wrestler 2025-09-03 14:22:25 -04:00
theelk801
e26c094b26 [SPM] Implement Damage Control Crew 2025-09-03 14:21:25 -04:00
theelk801
edad932077 [SPM] Implement School Daze 2025-09-03 14:18:38 -04:00
theelk801
785b45fdf8 [SPM] Implement Common Crook 2025-09-03 14:16:48 -04:00
theelk801
f9be1e4abe [SPM] Implement Supportive Parents 2025-09-03 14:15:47 -04:00
theelk801
953f9b54fa [SPM] update spoiler 2025-09-03 14:14:35 -04:00
theelk801
f5c3d01d70 [SPM] Implement Rocket-Powered Goblin Glider 2025-09-03 10:27:05 -04:00
theelk801
28174827df [SPM] Implement Scarlet Spider, Kaine 2025-09-03 10:24:23 -04:00
theelk801
c5bd744c00 [SPM] Implement Pumpkin Bombardment 2025-09-03 10:22:24 -04:00
theelk801
17014b2dd4 [SPM] Implement Prison Break 2025-09-03 10:20:49 -04:00
theelk801
0eee8fbb3f [SPM] Implement Spinneret and Spiderling 2025-09-03 10:19:01 -04:00
theelk801
6086a04ece [SPM] Implement Araña, Heart of the Spider 2025-09-03 10:14:22 -04:00
theelk801
9b295448cd [SPM] Implement Skyward Spider 2025-09-03 10:11:17 -04:00
theelk801
cf586d0b8f [SPM] Implement Cosmic Spider-Man 2025-09-03 10:02:39 -04:00
theelk801
f02bd66852 [SPM] Implement Chameleon, Master of Disguise 2025-09-03 09:58:56 -04:00
theelk801
9462bd89a8 [SPM] update spoiler 2025-09-03 09:56:53 -04:00
theelk801
fa21c0e619 [SPM] Implement Spider-UK 2025-09-02 17:19:24 -04:00
theelk801
bd0fbaeef9 [SPM] Implement Ominous Asylum 2025-09-02 17:12:30 -04:00
theelk801
58d672462a [SPM] update spoiler 2025-09-02 17:10:49 -04:00
theelk801
5faf68144a fix other verify failures 2025-09-02 17:09:28 -04:00
theelk801
26ab143ccb proper fix 2025-09-02 16:09:18 -04:00
theelk801
5b8103003c fix verify failure 2025-09-02 15:34:44 -04:00
theelk801
0a4f2be833 [SPM] Implement Spiders-Man, Heroic Horde 2025-09-02 11:54:29 -04:00
theelk801
482c7a9443 [SPM] Implement Impostor Syndrome 2025-09-02 11:38:58 -04:00
jmlundeen
693a6f2213 [TDC] fix Parapet Thrasher triggered Ability 2025-09-02 07:52:32 -05:00
jmlundeen
8656548676 [MKC] Implement Serene Sleuth 2025-09-01 14:12:31 -05:00
theelk801
78694fce0b [SPM] Implement Agent Venom 2025-09-01 13:28:04 -04:00
theelk801
811bf61ca7 [SPM] Implement Peter Parker's Camera 2025-09-01 13:24:20 -04:00
theelk801
7b0c3c8801 [SPM] Implement Web of Life and Destiny 2025-09-01 13:19:36 -04:00
theelk801
9e54ac477e [SPM] Implement Rent Is Due 2025-09-01 13:18:29 -04:00
theelk801
e22055b697 [SPM] Implement Radioactive Spider 2025-09-01 13:11:58 -04:00
theelk801
238e78c811 [SPM] Implement Flash Thompson, Spider-Fan 2025-09-01 13:09:40 -04:00
theelk801
45aa4717ad [SPM] Implement Ezekiel Sims, Spider-Totem 2025-09-01 13:07:43 -04:00
theelk801
2edd2e7926 [SPM] update spoiler 2025-09-01 13:05:43 -04:00
Steven Knipe
186d4a5f23 Test and fix Ravenous Slime not exiling when it dies simultaneously 2025-08-31 16:14:23 -07:00
jmlundeen
0254fc0d2a [SPM] Implement Steel Wrecking Ball 2025-08-31 15:51:05 -05:00
jmlundeen
4a6f3baca2 update spoiler 2025-08-31 15:23:09 -05:00
jmlundeen
2093091da2 [SPM] fix Gwen Stacy play land or cast spell 2025-08-31 10:46:48 -05:00
jmlundeen
60c56aab2f update missing leftHalfCard calls 2025-08-31 10:29:52 -05:00
jmlundeen
ef249d1ada [SPM] implement Gwen Stacy 2025-08-31 08:45:58 -05:00
jmlundeen
e65e67c125 [BIG] update Esoteric Duplicator test 2025-08-31 08:10:03 -05:00
jmlundeen
ce8f7d9493 [SPM] update Peter Parker test 2025-08-31 08:08:00 -05:00
jmlundeen
9021a7bd8a [SPM] Implement The Clone Saga 2025-08-31 00:23:26 -05:00
jmlundeen
480ac32cb0 [SPM] Implement Norman Osborn / Green Goblin 2025-08-30 23:11:31 -05:00
jmlundeen
454683682d [SPM] Implement Kraven, the Hunter 2025-08-30 22:57:48 -05:00
jmlundeen
1a550b48d7 [SPM] Electro, Assaulting Battery 2025-08-30 22:39:12 -05:00
jmlundeen
86cd18beb9 [SPM] Implement Peter Parker / Amazing Spider-Man 2025-08-30 22:37:14 -05:00
theelk801
7b9a72f758 fix verify failure 2025-08-30 20:26:18 -04:00
theelk801
c0fc991f6a [SPM] Implement Eddie Brock / Venom, Lethal Protector 2025-08-30 17:20:23 -04:00
theelk801
1b08a2e2f7 [SPM] Implement Pictures of Spider-Man 2025-08-30 16:43:30 -04:00
theelk801
897fb087c1 [SPM] update spoiler 2025-08-30 16:40:03 -04:00
theelk801
2db69b4ba5 [SPM] Implement Miles Morales / Ultimate Spider-Man 2025-08-30 16:39:17 -04:00
theelk801
49a3b1176e [SPM] Implement With Great Power... 2025-08-30 16:18:55 -04:00
jmlundeen
8e0a222f9b [SPM] Implement Spider-Punk 2025-08-30 15:10:43 -05:00
Grath
642362e99d [DSK] Implement Undead Sprinter 2025-08-30 13:03:40 -04:00
theelk801
963e516666 [SPM] Implement Rhino, Barreling Brute 2025-08-30 08:45:52 -04:00
theelk801
90f860c64a [SPM] update spoiler 2025-08-30 08:38:56 -04:00
ReSech
0adbc7c0c3
tests: added verify tests for retro and full art images (#13912)
* Add promoTypes and isTextless fields to MtgJsonCard; enhance VerifyCardDataTest for full art validation

* whitespace fixes

* Add null check

* Split Retro and FullArt to seperate Test

* Refactor VerifyCardDataTest to consolidate full art setting checks for poster promoType and textless cards

* Add validation for full art lands in VerifyCardDataTest

* Remove duplicate checks in checkWrongCardsDataInSets and add "not use" checks
2025-08-30 13:47:51 +04:00
theelk801
5d034fcb0c [SPM] fix Sandman, Shifting Scoundrel mana cost 2025-08-29 22:59:18 -04:00
theelk801
17ffb8afe9 fix verify failure 2025-08-29 22:59:04 -04:00
theelk801
37c4d00395 [SPM] Implement Sandman, Shifting Scoundrel 2025-08-29 22:38:51 -04:00
theelk801
1427a6de1c [SPM] Implement Daily Bugle Building 2025-08-29 22:32:42 -04:00
theelk801
51b386baa6 [SPM] Implement Spider-Suit 2025-08-29 22:30:16 -04:00
theelk801
56ad1fb16e [SPM] Implement Vulture, Scheming Scavenger 2025-08-29 22:30:16 -04:00
theelk801
7b3102af5d [SPM] Implement Ultimate Green Goblin 2025-08-29 22:30:15 -04:00
theelk801
0ee188226f [SPM] Implement Spider-Man India 2025-08-29 22:30:15 -04:00
theelk801
03d4fb70a6 [SPM] Implement Prowler, Clawed Thief 2025-08-29 22:30:15 -04:00
theelk801
6a562ea431 [SPM] Implement Raging Goblinoids 2025-08-29 22:30:15 -04:00
theelk801
ffdc2a9129 [SPM] Implement Behold the Sinister Six 2025-08-29 22:30:15 -04:00
theelk801
fe7b9e3e98 [SPM] Implement Mysterio, Master of Illusion 2025-08-29 22:30:13 -04:00
theelk801
8716606f0c [SPM] Implement Costume Closet 2025-08-29 22:29:24 -04:00
theelk801
0bb9b4468d [SPM] Implement City Pigeon 2025-08-29 22:29:24 -04:00
theelk801
6700e777f5 [SPM] update spoiler 2025-08-29 22:29:23 -04:00
ReSech
37fb493de1
images: improved full art images in some sets (#13935)
* AKR FULL_ART

* DFT FULL_ART

* FIN FULL_ART

* P08 FULL_ART

* PANA FULL_ART

* PF19 FULL_ART

* PF20 FULL_ART

* PL22 FULL_ART

* PRM FULL_ART

* USG RETRO

* Add UGL_FULL_ART_BASIC to isRetroFrame

* SPM FULL_ART
2025-08-30 06:24:52 +04:00
ReSech
82e08b244a
images: improved cards rendering with full art like poster cards (#13911)
* SLP Poster Cards to FULL_ART

* Full_ART Fixes for SLD

* FULL_ART LTR

* EOE FULL_ART

* DSC FULL_ART

* SLD Rervsible FULL_ART
2025-08-30 04:22:51 +04:00
ReSech
f142d07440
deck: added many old and new promo sets and miss cards (#13903)
* deck: added Bitter Triumph, Fable of the Mirror-Breaker, and Slickshot Show-off to Store Championships set

* added Monstrous Rage and Trinket Mage to Wizards Play Network 2025 set

* add Year of the Snake 2025 expansion set

* add Year of the Dragon 2024 expansion set

* deck: add Dragon and Snake tokens for PL24 and PL25

* add Year of the Dragon 2024 and Year of the Snake 2025 expansion sets

* add Reflection of Kiki-Jiki to Store Championships set

* hasBasicLands true for Year of the Dragon 2024 and Year of the Snake 2025

* Update URLs and Land rarity

* add MagicFest 2024 expansion set

* add Love Your LGS 2024 expansion set

* add MKM Standard Showdown expansion set

* Set Full Art Lands to Full Art

* Add new expansion sets: MagicFest 2024, MKM Standard Showdown, and Love Your LGS 2024

* Fix Error

* Add new expansion sets: MagicFest 2023 and 30th Anniversary History Promos

* Add new expansion sets: Love Your LGS 2022 and Regional Championship Qualifiers 2022

* Add Love Your LGS 2020 set

* Add new cards to PURL

* Update MagicFest 2025 set: add new cards and reorder existing entries

* Add Magiccon Cards
2025-08-30 04:18:54 +04:00
jmlundeen
d13a0e6e6b create token copy checks for copyfrom
* Esoteric Duplicator test demonstrates fix. Sculpting steel token was not coming back as an Esoteric Duplicator
2025-08-29 15:54:31 -05:00
jmlundeen
71cd3ce3fc update gen-list-unimplemented-cards-for-set
* remove periods from camel case name
2025-08-29 15:48:12 -05:00
jmlundeen
33c19fbc0f [SPM] Implement Carnage, Crimson Chaos 2025-08-29 15:46:34 -05:00
jmlundeen
3c6a18f24e [SPM] Implement Gwenom, Remorseless 2025-08-29 14:56:01 -05:00
jmlundeen
d59136cc33 update gen-list-unimplemented-cards-for-set to match current GitHub template 2025-08-29 14:55:56 -05:00
Grath
55ded952bc [FIN] Fix Zodiark, Umbral God to only count creatures. 2025-08-29 14:25:19 -04:00
jmlundeen
9921648522 [SPM] Implement Multiversal Passage 2025-08-29 12:19:26 -05:00
Grath
ef9f917c59 [OTC] Implement Forger's Foundry 2025-08-29 13:10:27 -04:00
jmlundeen
c3420bbc89 fix card test script generator indentation 2025-08-29 08:59:31 -05:00
jmlundeen
3fa021a295 add test coverage 2025-08-28 22:37:42 -05:00
jmlundeen
7129c02d86 add subtypes for infinity stone
- Infinity
- Stone
2025-08-28 21:33:16 -05:00
jmlundeen
1ed4f5a373 add script to generate card test classes 2025-08-28 21:23:55 -05:00
jmlundeen
df216677cd [SPM] update spoiler 2025-08-28 21:22:55 -05:00
Grath
d3957259ac Fix filter on Balthier and Fran 2025-08-28 13:22:15 -04:00
theelk801
31ef208f34 [SPM] Implement Symbiote Spider-Man 2025-08-28 09:50:13 -04:00
theelk801
36aaf3460f [SPE] fix Sensational Spider-Man not targeting at all 2025-08-28 09:43:44 -04:00
theelk801
0835f49ba3 [SPM] Implement J. Jonah Jameson 2025-08-28 09:43:02 -04:00
Jmlundeen
47f2eb4c94
update cards and effects that missed canPaySacrificeCost (#13916)
* update SacrificeAttachmentCost to work with canPaySacrificeCost

* update SacrificeXTargetCost to use canPaySacrificeCost

* update SacrificeXManaValueCost to use canPaySacrificeCost and getMaxValue

* update Phyrexian Dreadnought to use canPaySacrificeCost

* enable testNahiriSacrificePrevented test
2025-08-27 21:38:02 -05:00
Grath
366ffbb1e0 Portal Manipulator should work during any declare attackers step, not just the controller's. 2025-08-27 21:51:19 -04:00
Grath
ef475de29e [MKC] Implement Unexplained Absence 2025-08-27 10:03:14 -04:00
Steven Knipe
60be7070d6 Mass rename getSourceObjectZoneChangeCounter to getStackMomentSourceZCC, un-deprecate and change comment 2025-08-26 01:15:04 -07:00
oscscull
f674034cdf
Fix Dragon's Fire targeting issue (#13756) 2025-08-26 00:36:50 -07:00
Steven Knipe
924585cb86 Fix OrTriggeredAbility interaction with AtStepTriggeredAbility, remove unneeded RazorPendulum withTargetPointerSet 2025-08-25 22:02:52 -07:00
Steven Knipe
2ec9b8efa9 Improve CrackInTimeTest to check both trigger conditions 2025-08-25 21:53:37 -07:00
Grath
ae7e6a9c10
Refactor: Actually use DependencyType.BecomeNonbasicLand where it's needed. 2025-08-24 15:16:52 -04:00
Grath
3dea6f9a84 Add dependencies to Ragost's become-food ability. 2025-08-24 02:06:16 -04:00
220763b685 Merge pull request 'master' (#39) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 15m40s
Reviewed-on: #39
2025-08-23 20:25:00 -07:00
Grath
3c33531243 Finish fixing dependencies on land-changing effects. 2025-08-23 16:33:36 -04:00
Grath
65dae3e97b Remove depending on other land-type changing effects 2025-08-23 11:36:05 -04:00
Grath
f5b6c31152 Attempt to fix test by marking dependencies on other land-type changing effects. 2025-08-23 00:24:35 -04:00
Grath
848ea5a903 Fix typos, redundant/incorrect dependency additions. 2025-08-22 23:03:36 -04:00
Grath
370ce47303 Cover non-universal type change effects that also say 'land'. 2025-08-22 22:53:48 -04:00
Grath
c7f92a093b Refactor to use DependencyType.BecomesNonbasicLand to track effects which add land type. 2025-08-22 22:38:22 -04:00
Grath
b085446d04 Include game parameter. 2025-08-22 13:22:29 -04:00
Grath
f3d6855965 Fix the other two effects which exchange life totals with power/toughness to check to make sure that the permanent is a creature. 2025-08-22 12:17:56 -04:00
Grath
dd67682c12 Make Tree of Perdition's effect check to make sure that it's a creature before swapping toughness, because noncreatures do not have toughness. 2025-08-22 12:15:29 -04:00
jmlundeen
ca8b02d5ab increase test coverage 2025-08-19 11:26:52 -05:00
Grath
895c99d282 [EOE] Consult the Star Charts needs LandsYouControlCount not ManaSpentToCastCount. 2025-08-18 12:08:06 -04:00
jmlundeen
8b636b9926 disable testNahiriSacrificePrevented test
* will enable with #13916
2025-08-17 14:49:39 -05:00
jmlundeen
0651825e6d add test coverage for Jaya, Fiery Negotiator emblem 2025-08-17 12:26:50 -05:00
jmlundeen
b0ee19d782 fix Stalwart Successor checking permanents entering 2025-08-17 12:26:23 -05:00
jmlundeen
c16b3d6056 add tests to increase coverage 2025-08-17 10:59:01 -05:00
jmlundeen
4410374840 fix An-Havva Constable passing incorrect id to battlefield count function 2025-08-17 10:58:32 -05:00
jmlundeen
e6da7ed600 fix Alpine Moon incorrectly removing abilities in layer 4 2025-08-17 10:57:43 -05:00
jmlundeen
abe8a4356e increase test coverage for sacrifice effects 2025-08-17 09:46:17 -05:00
jmlundeen
985390b7c3 fix Dark Impostor and add test coverage 2025-08-17 09:45:47 -05:00
jmlundeen
b6de7f8406 remove unused imports from DeathriteShaman 2025-08-17 09:45:02 -05:00
theelk801
64558dc5fd fix verify failure 2025-08-16 18:44:55 -04:00
Evan Kranzler
910dbe0f0a
fix verify error 2025-08-16 12:58:56 -04:00
theelk801
f304cc545a [TLA] Implement The Rise of Sozin / Fire Lord Sozin 2025-08-16 10:52:25 -04:00
theelk801
d38d0d8719 [TLA] Implement Momo, Friendly Flier 2025-08-16 10:32:12 -04:00
theelk801
f0572e6099 [TLA] Implement Hakoda, Selfless Commander 2025-08-16 10:21:08 -04:00
theelk801
13d4ee1d65 [TLA] update spoiler 2025-08-16 10:17:40 -04:00
theelk801
b3c0090fba [TLE] update spoiler 2025-08-16 10:17:19 -04:00
Grath
faedb81a5c [PIP] Rex doesn't restrict stolen abilities to only once per turn. 2025-08-15 20:47:25 -04:00
theelk801
168e2a27ec fix verify failure 2025-08-15 16:58:14 -04:00
theelk801
6008dc279e [TLA] Implement Aang's Journey 2025-08-15 16:52:49 -04:00
jmlundeen
b470f0b679 update Urianger Augurelt to support full cost reduction 2025-08-15 15:39:28 -05:00
Evan Kranzler
b64f1dce45
[TLA] Implement Razor Rings, rework excess damage (#13910)
* [TLA] Implement Razor Rings

* add overflow protection
2025-08-15 16:37:55 -04:00
01ef3b0957 Merge pull request 'master' (#38) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 10m49s
Reviewed-on: #38
2025-08-15 12:14:13 -07:00
09f78c6240 fix whitelists
Some checks failed
/ build_release (push) Has been cancelled
2025-08-15 12:12:06 -07:00
theelk801
96dbfc757e fix error 2025-08-15 14:40:57 -04:00
theelk801
ea2dca6410 [TLA] Implement Sokka, Lateral Strategist 2025-08-15 14:23:01 -04:00
theelk801
c28facf759 [TLA] Implement Long Feng, Grand Secretariat 2025-08-15 14:20:51 -04:00
theelk801
5a78f79f32 [TLA] Implement Serpent of the Pass 2025-08-15 14:15:34 -04:00
theelk801
855bfabf24 [TLA] Implement How to Start a Riot 2025-08-15 14:07:15 -04:00
theelk801
0df1c4b128 [TLA] Implement Buzzard-Wasp Colony 2025-08-15 11:03:53 -04:00
theelk801
5f8f0c96f3 [TLA] Implement Flopsie, Bumi's Buddy 2025-08-15 10:58:31 -04:00
theelk801
2202bd4453 [TLA] Implement Hei Bai, Spirit of Balance 2025-08-15 10:55:00 -04:00
theelk801
f3447ffc87 [TLA] Implement Path to Redemption 2025-08-15 10:52:35 -04:00
theelk801
d0fa2bc125 [TLE] Implement Seismic Tutelage 2025-08-15 10:49:34 -04:00
theelk801
5d5ce4e0ab [TLE] Implement Lost in the Spirit World 2025-08-15 10:47:44 -04:00
theelk801
3b5ee47175 [TLE] Implement Lion Vulture 2025-08-15 09:21:37 -04:00
theelk801
37b4146171 [TLE] Implement Zuko, Avatar Hunter 2025-08-15 09:18:44 -04:00
theelk801
b3c699ef6e [TLE] Implement Warship Scout 2025-08-15 09:17:39 -04:00
theelk801
ef2e4858a3 [TLE] Implement Turtle-Seals 2025-08-15 09:17:16 -04:00
theelk801
1b87743605 [TLE] Implement Sokka, Wolf Cove's Protector 2025-08-15 09:16:54 -04:00
theelk801
65616841cb [TLE] Implement Sledding Otter-Penguin 2025-08-15 09:16:25 -04:00
theelk801
6549368417 [TLE] Implement Roku's Mastery 2025-08-15 09:15:29 -04:00
theelk801
ee7ce743e4 [TLE] Implement Purple Pentapus 2025-08-15 09:13:08 -04:00
theelk801
d7e5dee77e [TLE] Implement Momo, Rambunctious Rascal 2025-08-15 09:11:36 -04:00
theelk801
10989bc86c [TLE] Implement Mechanical Glider 2025-08-15 09:09:53 -04:00
theelk801
66d0a81264 [TLE] Implement Match the Odds 2025-08-15 09:08:59 -04:00
theelk801
416e64f3a0 [TLE] Implement Loyal Fire Sage 2025-08-15 09:05:02 -04:00
theelk801
ffa1ef10b7 [TLE] Implement Kyoshi Warrior Guard 2025-08-15 09:04:07 -04:00
theelk801
2cbae4a9ee [TLE] Implement Komodo Rhino 2025-08-15 09:03:40 -04:00
theelk801
6d295a1777 [TLE] Implement Katara, Heroic Healer 2025-08-15 09:03:12 -04:00
theelk801
ea09727e96 [TLE] Implement Iroh, Firebending Instructor 2025-08-15 09:02:07 -04:00
theelk801
47c70bdc2d [TLE] Implement Hippo-Cows 2025-08-15 09:00:46 -04:00
theelk801
8aceff16b0 [TLE] Implement Gilacorn 2025-08-15 09:00:37 -04:00
theelk801
f452640a71 [TLE] Implement Frog-Squirrels 2025-08-15 09:00:29 -04:00
theelk801
c7f2bae792 [TLE] Implement Flying Dolphin-Fish 2025-08-15 09:00:17 -04:00
theelk801
268a1c8339 [TLE] Implement Fire Nation Sentinels 2025-08-15 08:56:37 -04:00
theelk801
a9d728080e [TLE] Implement Fire Nation's Conquest 2025-08-15 08:53:53 -04:00
theelk801
8474f739e2 [TLE] Implement Fire Nation Archers 2025-08-15 08:53:12 -04:00
theelk801
a23d5f82e2 [TLE] Implement Earthbending Studen 2025-08-15 08:53:04 -04:00
theelk801
505a0b66f7 [TLA] Implement Watery Grasp 2025-08-15 08:47:33 -04:00
theelk801
78237b6b8b [TLA] Implement Waterbending Lesson 2025-08-15 08:43:55 -04:00
theelk801
e10b9fb7b9 [TLA] Implement Vindictive Warden 2025-08-15 08:40:18 -04:00
theelk801
935a389a05 [TLA] Implement Turtle-Duck 2025-08-15 08:39:33 -04:00
theelk801
93f1008170 [TLA] Implement Toph, the Blind Bandit 2025-08-15 08:37:56 -04:00
theelk801
cb28ffb1ab [TLA] Implement Suki, Kyoshi Warrior 2025-08-15 08:33:39 -04:00
theelk801
7be8f96063 [TLA] Implement Rowdy Snowballers 2025-08-15 08:31:41 -04:00
theelk801
1b396d68c6 [TLA] Implement Rough Rhino Cavalry 2025-08-15 08:30:31 -04:00
theelk801
4de08db7f5 [TLA] Implement Rocky Rebuke 2025-08-15 08:29:16 -04:00
theelk801
309d7415a0 [TLA] Implement Raucous Audience 2025-08-15 08:27:25 -04:00
theelk801
c2893d89a2 [TLA] Implement Rabaroo Troop 2025-08-15 08:25:29 -04:00
theelk801
e8c04a5896 [TLA] Implement Pillar Launch 2025-08-15 08:23:53 -04:00
theelk801
60ed1b7e6d [TLA] Implement Otter-Penguin 2025-08-15 08:22:13 -04:00
theelk801
366c038f6e [TLA] Implement Ostrich Horse 2025-08-15 08:20:25 -04:00
theelk801
e34613f11e [TLA] Implement Mongoose Lizard 2025-08-15 08:19:07 -04:00
theelk801
31e9a2beb6 [TLA] Implement Merchant of Many Hats 2025-08-15 08:18:18 -04:00
theelk801
6677bd1754 [TLA] Implement Master Piandao 2025-08-15 08:17:15 -04:00
theelk801
936c0b3a9c [TLA] Implement Master Pakku 2025-08-15 08:15:23 -04:00
theelk801
f1e588faa3 [TLA] Implement Katara, Bending Prodigy 2025-08-15 08:10:42 -04:00
theelk801
82c0aab35a [TLA] Implement Jeong Jeong's Deserters 2025-08-15 08:09:14 -04:00
theelk801
790e938f40 [TLA] Implement Hog-Monkey 2025-08-15 08:08:00 -04:00
theelk801
3c25c1931c [TLA] Implement Giant Koi 2025-08-15 08:06:14 -04:00
theelk801
6f05e94e5f [TLA] Implement Geyser Leaper 2025-08-15 08:05:22 -04:00
theelk801
23d7ba2293 [TLA] Implement Flexible Waterbender 2025-08-15 08:04:34 -04:00
theelk801
4b2ea25e96 [TLA] Implement Fire Nation Engineer 2025-08-15 08:03:17 -04:00
theelk801
4c4137ac79 [TLA] Implement First-Time Flyer 2025-08-15 07:55:56 -04:00
theelk801
7f1c5c37a1 [TLA] Implement Fire Sages 2025-08-15 07:53:07 -04:00
theelk801
076dcf1cf9 [TLA] Implement Rebellious Captives 2025-08-15 07:51:55 -04:00
Steven Knipe
0fc1eba02c Fix for my incorrect fix 2025-08-15 04:01:18 -07:00
Steven Knipe
c70fcbab79 fix TopographyTracker applying to opponents' creatures 2025-08-15 03:34:33 -07:00
d73dbfba11 fix index + update alert
All checks were successful
/ build_release (push) Successful in 10m33s
2025-08-15 03:33:34 -07:00
8926bcf5c2 Merge pull request 'master' (#37) from External/mage:master into master
All checks were successful
/ build_release (push) Successful in 10m24s
Reviewed-on: #37
2025-08-15 02:39:20 -07:00
eaac06f1cb Merge pull request 'tagger' (#36) from tagger into master
Some checks failed
/ build_release (push) Has been cancelled
Reviewed-on: #36
2025-08-15 02:37:58 -07:00
ReSech
82a8d36558
images: fixed retro frame style for REN and RIN sets (#13908) 2025-08-15 09:12:47 +04:00
Oleg Agafonov
bfe218dd05 tests: disabled randomly failed AI test 2025-08-15 08:41:15 +04:00
Oleg Agafonov
7644d1895c merge fix 2025-08-15 08:18:46 +04:00
Oleg Agafonov
aa1915cd13 deck: added old promo sets with boosters: Renaissance and Rinascimento (close #13906); 2025-08-15 08:17:26 +04:00
theelk801
5bede15130 [TLA] Implement Yuyan Archers 2025-08-14 22:49:06 -04:00
theelk801
f293ff51d9 [TLA] Implement Glider Kids 2025-08-14 22:47:54 -04:00
theelk801
4286704c5a [TLA] Implement Iguana Parrot 2025-08-14 22:47:54 -04:00
theelk801
5b2944a213 [TLA] Implement It'll Quench Ya! 2025-08-14 22:47:54 -04:00
theelk801
b457a2e559 [TLA] Implement Ozai's Cruelty 2025-08-14 22:47:54 -04:00
theelk801
8ff46a2b40 [TLA] Implement Pretending Poxbearers 2025-08-14 22:47:54 -04:00
theelk801
69de331df0 [TLA] Implement Saber-Tooth Moose-Lion 2025-08-14 22:47:54 -04:00
theelk801
009298d1f1 [TLA] Implement Zuko, Exiled Prince 2025-08-14 22:47:54 -04:00
theelk801
dd6321abec [TLA] update spoiler and reprints 2025-08-14 22:47:54 -04:00
theelk801
9a43922b40 [TLE] Implement Fire Nation Ambushers 2025-08-14 22:47:54 -04:00
theelk801
93e709cc82 [TLE] Implement Fire Nation Soldier 2025-08-14 22:47:54 -04:00
theelk801
174ccedfae [TLE] Implement Explosive Shot 2025-08-14 22:47:54 -04:00
theelk801
6a175067cb [TLE] Implement The Terror of Serpent's Pass 2025-08-14 22:47:54 -04:00
theelk801
014e21d035 [TLE] Implement Tundra Wall 2025-08-14 22:47:54 -04:00
theelk801
3fd6ee8d6a [TLE] Implement Water Whip 2025-08-14 22:47:54 -04:00
theelk801
c6b631a5b4 [TLE] Implement Wolf Cove Villager 2025-08-14 22:47:54 -04:00
theelk801
6d883b5a77 [TLE] Implement Zuko's Offense 2025-08-14 22:47:54 -04:00
theelk801
a598d92eb2 [TLE] Implement Zhao, the Seething Flame 2025-08-14 22:47:54 -04:00
theelk801
38bb4422a6 [TLE] update spoiler and reprints 2025-08-14 22:47:54 -04:00
theelk801
80ba2a2dd0 [TLE] Implement Earth Rumble 2025-08-14 22:47:53 -04:00
theelk801
89702ad81d [TLE] Implement Cat-Gator 2025-08-14 22:47:53 -04:00
theelk801
2f85f46e32 [TLE] Implement Aang, Airbending Master 2025-08-14 22:47:53 -04:00
theelk801
c5a52232d0 [TLE] Implement The Cabbage Merchant 2025-08-14 22:47:18 -04:00
Grath
0ec783cfdc [TLE] Implement Aang, Airbending Master 2025-08-14 22:18:52 -04:00
Grath
32080c731f [TLA] Fix Haru not having a target. 2025-08-14 22:12:42 -04:00
Grath
9c6a2762bb [TLA] Implement Haru, Hidden Talent 2025-08-14 22:02:09 -04:00
Steven Knipe
5adff9bd51 Fix ThreeDogGalaxyNewsDJTokenEffect bug from variable shadowing 2025-08-14 17:17:52 -07:00
theelk801
3ecf58a3e1 [TLE] Implement Elephant-Rat 2025-08-14 14:36:37 -04:00
theelk801
12f52b24df [TLE] Implement Eel-Hounds 2025-08-14 14:36:11 -04:00
theelk801
35c5344a31 [TLE] Implement Dragon Moose 2025-08-14 14:34:46 -04:00
theelk801
07cd325711 [TLE] Implement Deny Entry 2025-08-14 14:34:11 -04:00
theelk801
f0572c7551 [TLE] Implement Capital Guard 2025-08-14 14:34:11 -04:00
theelk801
498084c530 [TLE] Implement Bumi, Eclectic Earthbender 2025-08-14 14:34:11 -04:00
theelk801
7e6185afa6 [TLE] Implement Appa, Aang's Companion 2025-08-14 14:34:11 -04:00
theelk801
d349c8eea0 [TLE] Implement Allied Teamwork 2025-08-14 14:34:11 -04:00
theelk801
42291c75af [TLE] Implement Aardvark Sloth 2025-08-14 14:34:11 -04:00
theelk801
2f594c8445 [TLE] Implement Aang's Defense 2025-08-14 14:34:11 -04:00
theelk801
01944d39bb [TLE] Implement Aang, Air Nomad 2025-08-14 14:34:10 -04:00
theelk801
cfeb1af64a [TLE] update spoiler and reprints 2025-08-14 14:34:10 -04:00
theelk801
c80f70deeb [TLA] Implement Earth Village Ruffians 2025-08-14 14:34:10 -04:00
theelk801
5c0411d02e [TLA] Implement Earth Kingdom Soldier 2025-08-14 14:34:10 -04:00
theelk801
3367622d35 [TLA] Implement Deserter's Disciple 2025-08-14 14:34:10 -04:00
theelk801
6067624df2 [TLA] Implement Dai Li Indoctrination 2025-08-14 14:34:10 -04:00
theelk801
a877ab3f1a [TLA] Implement Cat-Owl 2025-08-14 14:34:10 -04:00
theelk801
bfaba3069f [TLA] Implement Barrels of Blasting Jelly 2025-08-14 14:34:10 -04:00
theelk801
ade5935d1a [TLA] Implement Bender's Waterskin 2025-08-14 14:34:10 -04:00
theelk801
cac3be5c4a [TLA] Implement Beetle-Headed Merchants 2025-08-14 14:34:10 -04:00
theelk801
038c8f05ef [TLA] Implement Badgermole 2025-08-14 14:34:10 -04:00
theelk801
a5068798a2 [TLA] Implement Azula Always Lies 2025-08-14 14:34:10 -04:00
theelk801
32a1ff367d [TLA] Implement Airbending Lesson 2025-08-14 14:34:09 -04:00
theelk801
355e8c15bc remove temporary verify skip 2025-08-14 14:34:09 -04:00
theelk801
88dae5ff4b [TLA] Implement Abandon Attachments 2025-08-14 14:34:09 -04:00
theelk801
065a271f57 [TLA] Implement Aang, the Last Airbender 2025-08-14 14:34:09 -04:00
theelk801
dd83ccb095 [TLA] update spoiler 2025-08-14 14:34:09 -04:00
jmlundeen
ec2c7e6ad6 [TDM] change Mistrise Village effect duration to end of turn and add discard logic
* effect now has end of turn duration and is discarded after resolving the next spell
2025-08-14 13:16:28 -05:00
jmlundeen
b8504d56f2 fix CantBeCounteredSourceEffect info message saying spell can't be countered by itself 2025-08-14 11:44:19 -05:00
jmlundeen
05e304e621 [TDM] fix Mistrise Village effect
* Add additional tests and fix effect to only work on next spell cast
* closes #13891
2025-08-13 16:28:25 -05:00
theelk801
ef270721a5 [TLA] Implement Fire Lord Zuko 2025-08-13 12:00:37 -04:00
theelk801
43ac278946 [TLA] Implement Fated Firepower 2025-08-13 12:00:37 -04:00
theelk801
0865b94875 [TLA] Implement Avatar Aang / Aang, Master of Elements 2025-08-13 12:00:37 -04:00
Steven Knipe
84a7e9f5b8 Simplify Transform triggers, fix Wildsong Howler 2025-08-12 23:35:52 -07:00
theelk801
16c789aaf7 [TLA] Implement Katara, Water Tribe's Hope 2025-08-12 20:58:39 -04:00
theelk801
9828e56590 [TLA] waterbend is a cost, not an ability 2025-08-12 20:54:38 -04:00
theelk801
7a241a6f1e [TLA] Implement Toph, the First Metalbender 2025-08-12 20:39:22 -04:00
Steven Knipe
2552dcf633 Fix and test token saga zcc tracking 2025-08-10 18:19:41 -07:00
ssk97
4683e5c05a Fix saga first chapter zcc (#13710)
* Enable disabled tests

* Enable zcc Saga fix

* Remove existing zcc hacks

(cherry picked from commit 19f980c2ce)
2025-07-07 10:15:21 +04:00
1910 changed files with 64695 additions and 16924 deletions

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-client</artifactId>
@ -133,7 +133,7 @@
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-transcoder</artifactId>
<version>1.17</version>
<version>1.19</version>
</dependency>
<!-- svg support END -->

View file

@ -575,7 +575,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
// Constants
private static final int DEFAULT_COUNT_LABEL_HEIGHT = 40; // can contain 1 or 2 lines
public static final int GRID_PADDING = 20;
public static final int GRID_PADDING = 12;
private static final ImageIcon INSERT_ROW_ICON = new ImageIcon(DragCardGrid.class.getClassLoader().getResource("editor_insert_row.png"));
private static final ImageIcon INSERT_COL_ICON = new ImageIcon(DragCardGrid.class.getClassLoader().getResource("editor_insert_col.png"));

View file

@ -39,10 +39,9 @@ public class BracketLegalityLabel extends LegalityLabel {
private static final Logger logger = Logger.getLogger(BracketLegalityLabel.class);
private static final String GROUP_GAME_CHANGES = "Game Changers";
private static final String GROUP_INFINITE_COMBOS = "Infinite Combos";
private static final String GROUP_INFINITE_COMBOS = "Early-game 2-Card Combos";
private static final String GROUP_MASS_LAND_DESTRUCTION = "Mass Land Destruction";
private static final String GROUP_EXTRA_TURN = "Extra Turns";
private static final String GROUP_TUTORS = "Tutors";
private static final Map<String, List<Integer>> MAX_GROUP_LIMITS = new LinkedHashMap<>();
@ -78,8 +77,6 @@ public class BracketLegalityLabel extends LegalityLabel {
Arrays.asList(0, 0, 0, 0, 99, 99));
MAX_GROUP_LIMITS.put(GROUP_EXTRA_TURN,
Arrays.asList(0, 0, 0, 3, 99, 99));
MAX_GROUP_LIMITS.put(GROUP_TUTORS,
Arrays.asList(0, 3, 3, 99, 99, 99));
}
private static final String RESOURCE_INFINITE_COMBOS = "brackets/infinite-combos.txt";
@ -92,7 +89,6 @@ public class BracketLegalityLabel extends LegalityLabel {
private final List<String> foundInfiniteCombos = new ArrayList<>();
private final List<String> foundMassLandDestruction = new ArrayList<>();
private final List<String> foundExtraTurn = new ArrayList<>();
private final List<String> foundTutors = new ArrayList<>();
private final List<String> badCards = new ArrayList<>();
private final List<String> fullGameChanges = new ArrayList<>();
@ -126,9 +122,6 @@ public class BracketLegalityLabel extends LegalityLabel {
if (this.foundExtraTurn.size() > getMaxCardsLimit(GROUP_EXTRA_TURN)) {
this.badCards.addAll(this.foundExtraTurn);
}
if (this.foundTutors.size() > getMaxCardsLimit(GROUP_TUTORS)) {
this.badCards.addAll(this.foundTutors);
}
}
private Integer getMaxCardsLimit(String groupName) {
@ -165,7 +158,6 @@ public class BracketLegalityLabel extends LegalityLabel {
groups.put(GROUP_INFINITE_COMBOS + getStats(GROUP_INFINITE_COMBOS), this.foundInfiniteCombos);
groups.put(GROUP_MASS_LAND_DESTRUCTION + getStats(GROUP_MASS_LAND_DESTRUCTION), this.foundMassLandDestruction);
groups.put(GROUP_EXTRA_TURN + getStats(GROUP_EXTRA_TURN), this.foundExtraTurn);
groups.put(GROUP_TUTORS + getStats(GROUP_TUTORS), this.foundTutors);
groups.forEach((group, cards) -> {
showInfo.add("<br>");
showInfo.add("<span style='font-weight:bold;font-size: " + infoFontTextSize + "px;'>" + group + "</span>");
@ -199,9 +191,6 @@ public class BracketLegalityLabel extends LegalityLabel {
case GROUP_EXTRA_TURN:
currentAmount = this.foundExtraTurn.size();
break;
case GROUP_TUTORS:
currentAmount = this.foundTutors.size();
break;
default:
throw new IllegalArgumentException("Unknown group " + groupName);
}
@ -222,7 +211,6 @@ public class BracketLegalityLabel extends LegalityLabel {
collectInfiniteCombos(deck);
collectMassLandDestruction(deck);
collectExtraTurn(deck);
collectTutors(deck);
}
private void collectGameChangers(Deck deck) {
@ -244,12 +232,9 @@ public class BracketLegalityLabel extends LegalityLabel {
"Consecrated Sphinx",
"Crop Rotation",
"Cyclonic Rift",
"Deflecting Swat",
"Enlightened Tutor",
"Expropriate",
"Field of the Dead",
"Fierce Guardianship",
"Food Chain",
"Force of Will",
"Gaea's Cradle",
"Gamble",
@ -261,8 +246,6 @@ public class BracketLegalityLabel extends LegalityLabel {
"Imperial Seal",
"Intuition",
"Jeska's Will",
"Jin-Gitaxias, Core Augur",
"Kinnan, Bonder Prodigy",
"Lion's Eye Diamond",
"Mana Vault",
"Mishra's Workshop",
@ -280,18 +263,13 @@ public class BracketLegalityLabel extends LegalityLabel {
"Serra's Sanctum",
"Smothering Tithe",
"Survival of the Fittest",
"Sway of the Stars",
"Teferi's Protection",
"Tergrid, God of Fright",
"Thassa's Oracle",
"The One Ring",
"The Tabernacle at Pendrell Vale",
"Underworld Breach",
"Urza, Lord High Artificer",
"Vampiric Tutor",
"Vorinclex, Voice of Hunger",
"Yuriko, the Tiger's Shadow",
"Winota, Joiner of Forces",
"Worldly Tutor"
));
}
@ -393,19 +371,6 @@ public class BracketLegalityLabel extends LegalityLabel {
.forEach(this.foundExtraTurn::add);
}
private void collectTutors(Deck deck) {
// edh power level uses search for land and non-land card, but bracket need only non-land cards searching
this.foundTutors.clear();
Stream.concat(deck.getCards().stream(), deck.getSideboard().stream())
.filter(card -> card.getRules().stream()
.map(s -> s.toLowerCase(Locale.ENGLISH))
.anyMatch(s -> s.contains("search your library") && !isTextContainsLandCard(s))
)
.map(Card::getName)
.sorted()
.forEach(this.foundTutors::add);
}
private boolean isTextContainsLandCard(String lowerText) {
// TODO: share code with AbstractCommander and edh power level
// TODO: add tests

View file

@ -21,6 +21,19 @@ public final class Constants {
}
public static final ImmutableList<Pair<String, String[]>> foulMagicsSets = ImmutableList.of(
new Pair<String, String[]>("Set 3 - Old Fat Men", new String[] {
"Ninth Edition",
"Tenth Edition",
"* Time Spiral Block",
"* Lorwyn Block",
"* Shards of Alara Block",
"Scars of Mirrodin",
"Zendikar",
"Rise of the Eldrazi",
"Worldwake",
"* Innistrad Block",
"Foul Magic Block 3 Extras"
}),
new Pair<String, String[]>("Set 2.5 - Ravnica Cultural Exchange", new String[] {
"* March of the Machine Block",
"* Phyrexia: All Will Be One Block",

View file

@ -36,6 +36,7 @@ public class TaggerModel extends AbstractTableModel {
private int recentSortedColumn;
private boolean recentAscending;
private Runnable doSort;
private int whitelistCount = 0;
public TaggerModel(Runnable sortFn) {
@ -46,14 +47,21 @@ public class TaggerModel extends AbstractTableModel {
placeholder.id = "";
placeholder.description = "Please download Scryfall tags from the 'download' tab & reopen";
placeholder.label = "Data missing!";
view.add(placeholder);
Tag placeholder2 = new Tag();
placeholder2.id = "";
placeholder2.description = "You may need do a Scryfall download to associate IDs";
placeholder2.label = "Also!";
view.add(placeholder2);
}
}
public void clear() {
view = TagRepository.instance.getAllTags();
filtered.clear();
this.whitelist.clear();
this.blacklist.clear();
fireTableDataChanged();
doSort.run();
}
@ -183,17 +191,32 @@ public class TaggerModel extends AbstractTableModel {
public Set<String> buildWhitelist() {
whitelist.clear();
whitelistCount = 0;
// whitelists are a bit weird, each one needs to reduce the next
Set<String> temp = new HashSet<String>();
boolean fresh = true;
for (String key : filtered.keySet()) {
temp.clear();
if (filtered.get(key)) {
whitelistCount++;
for (CardInfo card : TagRepository.instance.getCardsByTagId(key)) {
whitelist.add(card.getName());
temp.add(card.getName());
}
if (fresh) {
whitelist.addAll(temp);
} else {
whitelist.retainAll(temp);
}
fresh = false;
}
}
return whitelist;
}
public Set<String> buildBlacklist() {
blacklist.clear();
for (String key : filtered.keySet()) {

View file

@ -2120,6 +2120,9 @@
</Events>
</Component>
<Component class="javax.swing.JTextField" name="txtBackgroundImagePath">
<Properties>
<Property name="toolTipText" type="java.lang.String" value="The selected image will be used as the background picture. Requires client restart to see changes."/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnBrowseBackgroundImage">
<Properties>
@ -2259,16 +2262,13 @@
<SubComponents>
<Component class="javax.swing.JCheckBox" name="cbUseDefaultImageFolder">
<Properties>
<Property name="text" type="java.lang.String" value="Use default location to save images"/>
<Property name="text" type="java.lang.String" value="Use default location to save card images"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cbUseDefaultImageFolderActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="txtImageFolderPath">
<Properties>
<Property name="toolTipText" type="java.lang.String" value="The selected image will be used as background picture. You have to restart MAGE to view a changed background image."/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnBrowseImageLocation">
<Properties>

View file

@ -2162,6 +2162,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
}
});
txtBackgroundImagePath.setToolTipText("The selected image will be used as the background picture. Requires client restart to see changes.");
btnBrowseBackgroundImage.setText("Browse...");
btnBrowseBackgroundImage.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -2261,15 +2263,13 @@ public class PreferencesDialog extends javax.swing.JDialog {
panelCardImages.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Card images"));
cbUseDefaultImageFolder.setText("Use default location to save images");
cbUseDefaultImageFolder.setText("Use default location to save card images");
cbUseDefaultImageFolder.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cbUseDefaultImageFolderActionPerformed(evt);
}
});
txtImageFolderPath.setToolTipText("The selected image will be used as background picture. You have to restart MAGE to view a changed background image.");
btnBrowseImageLocation.setText("Browse...");
btnBrowseImageLocation.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -3523,7 +3523,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
dialog.txtImageFolderPath.setText(path);
updateCache(KEY_CARD_IMAGES_PATH, path);
}
load(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true");
load(prefs, dialog.cbSaveToZipFiles, KEY_CARD_IMAGES_SAVE_TO_ZIP, "true", "false");
dialog.cbPreferredImageLanguage.setSelectedItem(MageFrame.getPreferences().get(KEY_CARD_IMAGES_PREF_LANGUAGE, CardLanguage.ENGLISH.getCode()));
// rendering settings
@ -3713,7 +3713,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
}
public static boolean isSaveImagesToZip() {
return PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_SAVE_TO_ZIP, "true").equals("true");
return PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_SAVE_TO_ZIP, "false").equals("true");
}
private static void load(Preferences prefs, JCheckBox checkBox, String propName, String yesValue) {

View file

@ -1700,7 +1700,7 @@ public class TablesPanel extends javax.swing.JPanel {
MatchOptions options = new MatchOptions(gameName, gameType, multiPlayer);
options.getPlayerTypes().add(PlayerType.HUMAN);
options.getPlayerTypes().add(aiType);
for (int i=2 ; i < numPlayers ; i++) {
for (int i = 2; i < numPlayers; i++) {
options.getPlayerTypes().add(aiType);
}
options.setDeckType("Variant Magic - Freeform Commander");
@ -1719,9 +1719,9 @@ public class TablesPanel extends javax.swing.JPanel {
table = SessionHandler.createTable(roomId, options);
SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, testDeck, "");
SessionHandler.joinTable(roomId, table.getTableId(), "Computer", aiType, 1, testDeck, "");
for (int i=2 ; i < numPlayers ; i++) {
SessionHandler.joinTable(roomId, table.getTableId(), "Computer" + i, aiType, 1, testDeck, "");
SessionHandler.joinTable(roomId, table.getTableId(), "Computer" + (multiPlayer ? " 2" : ""), aiType, 1, testDeck, "");
for (int i = 2; i < numPlayers; i++) {
SessionHandler.joinTable(roomId, table.getTableId(), "Computer " + (i + 1), aiType, 1, testDeck, "");
}
SessionHandler.startMatch(roomId, table.getTableId());
} catch (HeadlessException ex) {

View file

@ -940,8 +940,13 @@ public abstract class CardPanel extends MagePermanent implements ComponentListen
private void setGameCardSides(CardView gameCard) {
if (this.cardSideMain == null) {
// new card
this.cardSideMain = gameCard;
this.cardSideOther = gameCard.getSecondCardFace();
if (gameCard instanceof PermanentView) {
this.cardSideMain = gameCard;
this.cardSideOther = gameCard.isTransformed() ? ((PermanentView) gameCard).getOriginal() : gameCard.getSecondCardFace();
} else {
this.cardSideMain = gameCard;
this.cardSideOther = gameCard.getSecondCardFace();
}
} else {
// updated card
if (this.cardSideMain.getName().equals(gameCard.getName())) {

View file

@ -109,11 +109,12 @@ public class GathererSets implements Iterable<DownloadJob> {
"NEC", "YNEO", "NEO", "SNC", "NCC", "CLB", "2X2", "DMU", "DMC", "40K", "GN3",
"UNF", "BRO", "BRC", "BOT", "J22", "DMR", "ONE", "ONC", "SCH",
"MOM", "MOC", "MUL", "MAT", "LTR", "CMM", "WOE", "WHO", "RVR", "WOT",
"WOC", "SPG", "LCI", "LCC", "REX", "PIP", "MKM", "MKC", "CLU", "OTJ",
"WOC", "SPG", "LCI", "LCC", "REX", "PIP", "YMKM", "MKM", "MKC", "CLU", "OTJ",
"OTC", "OTP", "BIG", "MH3", "M3C", "ACR", "BLB", "BLC", "DSK", "DSC",
"MB2", "FDN", "INR", "J25", "DRC", "DFT", "TDC", "TDM", "FCA", "FIC",
"FIN", "SIS", "SIR", "SLD", "AKR", "MD1", "ANB", "LTC", "BRR", "HA1",
"HA2", "HA3", "HA4", "HA5", "ZNC", "EOE", "EOC", "SPE", "TLA", "EOS"
"HA2", "HA3", "HA4", "HA5", "ZNC", "EOE", "EOC", "SPE", "TLA", "EOS",
"MAR", "SPM"
// "HHO", "ANA" -- do not exist on gatherer
};
@ -181,6 +182,7 @@ public class GathererSets implements Iterable<DownloadJob> {
codeReplacements.put("WTH", "WL");
codeReplacements.put("YMID", "Y22");
codeReplacements.put("YNEO", "Y22NEO");
}
public GathererSets() {

View file

@ -2,10 +2,16 @@ package org.mage.plugins.card.dl.sources;
import org.tritonus.share.ArraySet;
import mage.cards.CardSetInfo;
import mage.cards.CardWithHalves;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -28,6 +34,8 @@ public class ScryfallImageSupportCards {
add("2ED"); // Unlimited Edition
//add("CEI"); // Intl. Collectors Edition
//add("CED"); // Collectors Edition
add("RIN"); // Rinascimento
add("REN"); // Renaissance
add("ARN"); // Arabian Nights
add("ATQ"); // Antiquities
//add("FBB"); // Foreign Black Border
@ -465,6 +473,7 @@ public class ScryfallImageSupportCards {
// add("MD1"); // Modern Event Deck
// add("DD3"); // Duel Decks Anthology
// add("PZ1"); // Legendary Cube
add("PLG20"); // Love Your LGS 2020
add("IKO"); // Ikoria: Lair of Behemoths
add("C20"); // Commander 2020
add("M21"); // Core Set 2021
@ -514,11 +523,13 @@ public class ScryfallImageSupportCards {
add("NCC"); // New Capenna Commander
add("SLX"); // Universes Within
add("CLB"); // Commander Legends: Battle for Baldur's Gate
add("PLG22"); // Love Your LGS 2022
add("2X2"); // Double Masters 2022
add("SCH"); // Store Championships
add("DMU"); // Dominaria United
add("DMC"); // Dominaria United Commander
add("YDMU"); // Alchemy: Dominaria
add("PRCQ"); // Regional Championship Qualifiers 2022
add("40K"); // Warhammer 40,000 Commander
add("UNF"); // Unfinity
add("GN3"); // Game Night: Free-for-All
@ -530,7 +541,7 @@ public class ScryfallImageSupportCards {
add("SCD"); // Starter Commander Decks
add("PW23"); // Wizards Play Network 2023
add("P23"); // Judge Gift Cards 2023
add("SLC"); // Secret Lair 30th Anniversary Countdown Kit
add("SLC"); // Secret Lair Countdown
add("DMR"); // Dominaria Remastered
add("ONE"); // Phyrexia: All Will Be One
add("ONC"); // Phyrexia: All Will Be One Commander
@ -546,9 +557,11 @@ public class ScryfallImageSupportCards {
add("30A"); // 30th Anniversary Edition
add("P30A"); // 30th Anniversary Play Promos
add("P30M"); // 30th Anniversary Misc Promos
add("P30H"); // 30th Anniversary History Promos
add("PEWK"); // Eternal Weekend
add("LTR"); // The Lord of the Rings: Tales of Middle-Earth
add("LTC"); // Tales of Middle-Earth Commander
add("PF23"); // MagicFest 2023
add("CMM"); // Commander Masters
add("WHO"); // Doctor Who
add("WOE"); // Wilds of Eldraine
@ -559,10 +572,14 @@ public class ScryfallImageSupportCards {
add("REX"); // Jurassic World Collection
add("SPG"); // Special Guests
add("PW24"); // Wizards Play Network 2024
add("PF24"); // MagicFest 2024
add("RVR"); // Ravnica Remastered
add("PL24"); // Year of the Dragon 2024
add("PIP"); // Fallout
add("YMKM"); // Alchemy: Murders at Karlov Manor
add("MKM"); // Murders at Karlov Manor
add("MKC"); // Murders at Karlov Manor Commander
add("PSS4"); // MKM Standard Showdown
add("CLU"); // Ravnica: Clue Edition
add("OTJ"); // Outlaws of Thunder Junction
add("OTC"); // Outlaws of Thunder Junction Commander
@ -574,6 +591,7 @@ public class ScryfallImageSupportCards {
add("ACR"); // Assassin's Creed
add("BLB"); // Bloomburrow
add("BLC"); // Bloomburrow Commander
add("PLG24"); // Love Your LGS 2024
add("PCBB"); // Cowboy Bebop
add("MB2"); // Mystery Booster 2
add("DSK"); // Duskmourn: House of Horror
@ -585,6 +603,7 @@ public class ScryfallImageSupportCards {
add("PSPL"); // Spotlight Series
add("INR"); // Innistrad Remastered
add("PF25"); // MagicFest 2025
add("PL25"); // Year of the Snake 2025
add("DFT"); // Aetherdrift
add("DRC"); // Aetherdrift Commander
add("PLG25"); // Love Your LGS 2025
@ -599,11 +618,19 @@ public class ScryfallImageSupportCards {
add("EOS"); // Edge of Eternities: Stellar Sights
add("SPM"); // Marvel's Spider-Man
add("SPE"); // Marvel's Spider-Man Eternal
add("LMAR"); // Marvel Legends Series Inserts
add("MAR"); // Marvel Universe
add("TLA"); // Avatar: The Last Airbender
add("TLE"); // Avatar: The Last Airbender Eternal
add("ECL"); // Lorwyn Eclipsed
add("TMT"); // Teenage Mutant Ninja Turtles
add("TMC"); // Teenage Mutant Ninja Turtles Eternal
// Custom sets using Scryfall images - must provide a direct link for each card in directDownloadLinks
add("CALC"); // Custom Alchemized versions of existing cards
// Foul Magics sets
add("FMB3E");
}
};
@ -701,6 +728,7 @@ public class ScryfallImageSupportCards {
put("SLD/Sol Ring/1512b", "https://api.scryfall.com/cards/sld/1512/en?format=image&face=back");
put("SLD/Steely Resolve/1326b", "https://api.scryfall.com/cards/sld/1326/en?format=image&face=back");
put("SLD/Stitch in Time/382b", "https://api.scryfall.com/cards/sld/382/en?format=image&face=back");
put("SLD/Teferi's Ageless Insight/2214b", "https://api.scryfall.com/cards/sld/2214/en?format=image&face=back");
put("SLD/Terror/750b", "https://api.scryfall.com/cards/sld/750/en?format=image&face=back");
put("SLD/Tuvasa the Sunlit/1328b", "https://api.scryfall.com/cards/sld/1328/en?format=image&face=back");
put("SLD/Ulamog, the Ceaseless Hunger/1122b", "https://api.scryfall.com/cards/sld/1122/en?format=image&face=back");
@ -743,6 +771,32 @@ public class ScryfallImageSupportCards {
put("TDM/Scavenger Regent/379b", "https://api.scryfall.com/cards/tdm/379/en?format=image&face=back");
put("TDM/Ugin, Eye of the Storms/382b", "https://api.scryfall.com/cards/tdm/382/en?format=image&face=back");
for (ExpansionSet set : Sets.getInstance().values()) {
for (Integer key : set.cardAliases.keySet()) {
var value = set.cardAliases.get(key);
put(
String.format("%s/%s/%s", set.getCode(), value.cardInfo.getName(), value.cardInfo.getCardNumber()),
String.format("https://api.scryfall.com/cards/%s/%s/en?face=front&format=image", value.targetSet.toLowerCase(), value.targetSetNumber)
);
if (CardWithHalves.class.isAssignableFrom(value.cardInfo.getCardClass())) {
try {
UUID uid = UUID.randomUUID();
CardSetInfo info = new CardSetInfo(set.getName(), set.getCode(), value.targetSet, value.cardInfo.getRarity());
CardWithHalves backCard = (CardWithHalves) value.cardInfo.getCardClass().getDeclaredConstructor(UUID.class, CardSetInfo.class).newInstance(
uid, info);
put(
String.format("%s/%s/%s", set.getCode(), backCard.getRightHalfCard().getName(), value.cardInfo.getCardNumber()),
String.format("https://api.scryfall.com/cards/%s/%s/en?face=back", value.targetSet.toLowerCase(), value.targetSetNumber)
);
} catch (Exception e) {
System.out.println(e);
}
}
}
}
}
};
@ -766,6 +820,7 @@ public class ScryfallImageSupportCards {
if (directDownloadLinks.containsKey(linkCode2)) {
return linkCode2;
}
// default
return null;

View file

@ -1,10 +1,10 @@
package org.mage.plugins.card.dl.sources;
import mage.cards.repository.TokenRepository;
import java.util.HashMap;
import java.util.Map;
import mage.cards.repository.TokenRepository;
/**
* @author JayDi85
*/
@ -817,10 +817,13 @@ public class ScryfallImageSupportTokens {
// SLD
put("SLD/Angel", "https://api.scryfall.com/cards/sld/1340?format=image");
put("SLD/Blood", "https://api.scryfall.com/cards/sld/2180?format=image");
put("SLD/Cat/1", "https://api.scryfall.com/cards/sld/1517?format=image");
put("SLD/Cat/2", "https://api.scryfall.com/cards/sld/27?format=image");
put("SLD/Cat/3", "https://api.scryfall.com/cards/sld/28?format=image");
put("SLD/Clue", "https://api.scryfall.com/cards/sld/348/en?format=image");
put("SLD/Cordyceps Infected/1", "https://api.scryfall.com/cards/sld/2201?format=image");
put("SLD/Cordyceps Infected/2", "https://api.scryfall.com/cards/sld/2206?format=image");
put("SLD/Dog", "https://api.scryfall.com/cards/sld/1516?format=image");
put("SLD/Egg", "https://api.scryfall.com/cards/sld/1398?format=image");
put("SLD/Faerie Rogue/1", "https://api.scryfall.com/cards/sld/13/en?format=image");
@ -2221,7 +2224,7 @@ public class ScryfallImageSupportTokens {
put("WHO/Treasure/2", "https://api.scryfall.com/cards/twho/29?format=image");
put("WHO/Treasure/3", "https://api.scryfall.com/cards/twho/30?format=image");
put("WHO/Treasure/4", "https://api.scryfall.com/cards/twho/31?format=image");
put("WHO/Warrior", "https://api.scryfall.com/cards/twho/9?format=image");
put("WHO/Warrior", "https://api.scryfall.com/cards/twho/9?format=image");
// 8ED
put("8ED/Bird", "https://api.scryfall.com/cards/p03/7/en?format=image");
@ -2398,7 +2401,7 @@ public class ScryfallImageSupportTokens {
put("OTP/Human Warrior", "https://api.scryfall.com/cards/totp/3/en?format=image");
put("OTP/Pest", "https://api.scryfall.com/cards/totp/4/en?format=image");
// SCD
// SCD
put("SCD/Beast", "https://api.scryfall.com/cards/tscd/19/en?format=image");
put("SCD/Bird", "https://api.scryfall.com/cards/tscd/2/en?format=image");
put("SCD/Cat", "https://api.scryfall.com/cards/tscd/3/en?format=image");
@ -2546,6 +2549,7 @@ public class ScryfallImageSupportTokens {
// DSK
put("DSK/Beast", "https://api.scryfall.com/cards/tdsk/3?format=image");
put("DSK/Demon", "https://api.scryfall.com/cards/tdsk/9?format=image");
put("DSK/Emblem Kaito", "https://api.scryfall.com/cards/tdsk/17/en?format=image");
put("DSK/Everywhere", "https://api.scryfall.com/cards/tdsk/16?format=image");
put("DSK/Glimmer", "https://api.scryfall.com/cards/tdsk/4?format=image");
@ -2558,6 +2562,7 @@ public class ScryfallImageSupportTokens {
put("DSK/Spider", "https://api.scryfall.com/cards/tdsk/12?format=image");
put("DSK/Spirit/1", "https://api.scryfall.com/cards/tdsk/6?format=image");
put("DSK/Spirit/2", "https://api.scryfall.com/cards/tdsk/8?format=image");
put("DSK/Toy", "https://api.scryfall.com/cards/tdsk/7?format=image");
put("DSK/Treasure", "https://api.scryfall.com/cards/tdsk/15?format=image");
// DSC
@ -2738,7 +2743,7 @@ public class ScryfallImageSupportTokens {
put("ACR/Treasure", "https://api.scryfall.com/cards/tacr/6?format=image");
// DD2
put("DD2/Elemental Shaman", "https://api.scryfall.com/cards/tdd2/1?format=image");
put("DD2/Elemental Shaman", "https://api.scryfall.com/cards/tdd2/1?format=image");
// FIN
put("FIN/Hero/1", "https://api.scryfall.com/cards/tfin/2/en?format=image");
@ -2818,6 +2823,43 @@ public class ScryfallImageSupportTokens {
put("EOC/Shapeshifter", "https://api.scryfall.com/cards/teoc/2/en?format=image");
put("EOC/Thopter", "https://api.scryfall.com/cards/teoc/16/en?format=image");
// SPM
put("SPM/Food", "https://api.scryfall.com/cards/tspm/5?format=image");
put("SPM/Human", "https://api.scryfall.com/cards/tspm/4?format=image");
put("SPM/Illusion", "https://api.scryfall.com/cards/tspm/2?format=image");
put("SPM/Robot", "https://api.scryfall.com/cards/tspm/6?format=image");
put("SPM/Spider", "https://api.scryfall.com/cards/tspm/3?format=image");
put("SPM/Treasure", "https://api.scryfall.com/cards/tspm/7?format=image");
// TLA
put("TLA/Ally/1", "https://api.scryfall.com/cards/ttla/4/?format=image");
put("TLA/Ally/2", "https://api.scryfall.com/cards/ttla/5/?format=image");
put("TLA/Ally/3", "https://api.scryfall.com/cards/ttla/6/?format=image");
put("TLA/Ally/4", "https://api.scryfall.com/cards/ttla/7/?format=image");
put("TLA/Ally/5", "https://api.scryfall.com/cards/ttla/8/?format=image");
put("TLA/Ballistic Boulder", "https://api.scryfall.com/cards/ttla/13/?format=image");
put("TLA/Bear", "https://api.scryfall.com/cards/ttla/12/?format=image");
put("TLA/Clue/1", "https://api.scryfall.com/cards/ttla/14/?format=image");
put("TLA/Clue/2", "https://api.scryfall.com/cards/ttla/15/?format=image");
put("TLA/Clue/3", "https://api.scryfall.com/cards/ttla/16/?format=image");
put("TLA/Clue/4", "https://api.scryfall.com/cards/ttla/17/?format=image");
put("TLA/Clue/5", "https://api.scryfall.com/cards/ttla/18/?format=image");
put("TLA/Dragon", "https://api.scryfall.com/cards/ttla/9/?format=image");
put("TLA/Food/1", "https://api.scryfall.com/cards/ttla/19/?format=image");
put("TLA/Food/2", "https://api.scryfall.com/cards/ttla/20/?format=image");
put("TLA/Food/3", "https://api.scryfall.com/cards/ttla/21/?format=image");
put("TLA/Monk", "https://api.scryfall.com/cards/ttla/10/?format=image");
put("TLA/Soldier", "https://api.scryfall.com/cards/ttla/11/?format=image");
put("TLA/Spirit", "https://api.scryfall.com/cards/ttla/3/?format=image");
put("TLA/Treasure", "https://api.scryfall.com/cards/ttla/22?format=image");
// TLE
put("TLE/Marit Lage", "https://api.scryfall.com/cards/ttle/1/?format=image");
put("TLE/Soldier", "https://api.scryfall.com/cards/ttle/2?format=image");
// TMT
put("TMT/Mutagen", "https://api.scryfall.com/cards/ttmt/9?format=image");
// JVC
put("JVC/Elemental Shaman", "https://api.scryfall.com/cards/tjvc/4?format=image");
@ -2931,6 +2973,12 @@ public class ScryfallImageSupportTokens {
// PL23
put("PL23/Food", "https://api.scryfall.com/cards/pl23/2?format=image");
// PL24
put("PL24/Dragon", "https://api.scryfall.com/cards/pl24/3?format=image");
// PL25
put("PL25/Snake", "https://api.scryfall.com/cards/pl25/2?format=image");
// generate supported sets
supportedSets.clear();
for (String cardName : this.keySet()) {

View file

@ -558,12 +558,12 @@ public class DownloadPicturesService extends DefaultBoundedRangeModel implements
);
allCardsUrls.add(url);
}
if (card.isModalDoubleFacedCard()) {
if (card.getModalDoubleFacedSecondSideName() == null || card.getModalDoubleFacedSecondSideName().trim().isEmpty()) {
if (card.isDoubleFacedCard()) {
if (card.getDoubleFacedSecondSideName() == null || card.getDoubleFacedSecondSideName().trim().isEmpty()) {
throw new IllegalStateException("MDF card can't have empty name.");
}
CardDownloadData cardDownloadData = new CardDownloadData(
card.getModalDoubleFacedSecondSideName(),
card.getDoubleFacedSecondSideName(),
card.getSetCode(),
card.getCardNumber(),
card.usesVariousArt(),

View file

@ -82,7 +82,7 @@ public class ThemePluginImpl implements ThemePlugin {
}
if (ui.containsKey("gamePanel") && ui.containsKey("jLayeredPane")) {
ImagePanel bgPanel = new ImagePanel(backgroundImage, ImagePanelStyle.TILED);
ImagePanel bgPanel = new ImagePanel(backgroundImage, ImagePanelStyle.COVER);
// TODO: research - is all components used? And why it make transparent?
unsetOpaque(ui.get("splitChatAndLogs"));

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-common</artifactId>

View file

@ -78,6 +78,9 @@ public class ImagePanel extends JPanel {
case ACTUAL:
drawActual(g);
break;
case COVER:
drawCover(g);
break;
}
}
@ -99,4 +102,25 @@ public class ImagePanel extends JPanel {
float y = (d.height - image.getHeight(null)) * alignmentY;
g.drawImage(image, (int) x, (int) y, this);
}
private void drawCover(Graphics g) {
Dimension d = getSize();
int imageWidth = image.getWidth(null);
int imageHeight = image.getHeight(null);
// Calculate scale to cover the entire panel while maintaining aspect ratio
double scaleX = (double) d.width / imageWidth;
double scaleY = (double) d.height / imageHeight;
double scale = Math.max(scaleX, scaleY);
// Calculate the scaled dimensions
int scaledWidth = (int) (imageWidth * scale);
int scaledHeight = (int) (imageHeight * scale);
// Center the image
int x = (d.width - scaledWidth) / 2;
int y = (d.height - scaledHeight) / 2;
g.drawImage(image, x, y, scaledWidth, scaledHeight, null);
}
}

View file

@ -4,5 +4,5 @@ package mage.components;
* Created by IGOUDT on 7-3-2017.
*/
public enum ImagePanelStyle {
TILED, SCALED, ACTUAL
TILED, SCALED, ACTUAL, COVER
}

View file

@ -17,8 +17,8 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
// * launcher gives priority to 1.4.48 instead 1.4.48-any-text, so don't use empty release info
public static final int MAGE_VERSION_MAJOR = 1;
public static final int MAGE_VERSION_MINOR = 4;
public static final int MAGE_VERSION_RELEASE = 57;
public static final String MAGE_VERSION_RELEASE_INFO = "V2"; // V1, V1a, V1b for releases; V1-beta3, V1-beta4 for betas
public static final int MAGE_VERSION_RELEASE = 58;
public static final String MAGE_VERSION_RELEASE_INFO = "V1"; // V1, V1a, V1b for releases; V1-beta3, V1-beta4 for betas
// strict mode
// Each update requires a strict version

View file

@ -601,14 +601,13 @@ public final class SystemUtil {
continue;
}
Optional<Player> playerOptional = findPlayer(game, command.player);
if (!playerOptional.isPresent()) {
Player player = findPlayer(game, command.player, feedbackPlayer);
if (player == null) {
String mes = String.format("Unknown player: %s", line);
errorsList.add(mes);
logger.warn(mes);
continue;
}
Player player = playerOptional.get();
// SPECIAL token/emblem call (without SET name)
if ("token".equalsIgnoreCase(command.zone)) {
@ -860,17 +859,54 @@ public final class SystemUtil {
return false;
}
/**
* Find player by name.
*
* @param game
* @param name
* @return
*/
private static Optional<Player> findPlayer(Game game, String name) {
return game.getPlayers().values().stream()
.filter(player -> player.getName().equals(name)).findFirst();
private static Player findPlayer(Game game, String needName, Player feedbackPlayer) {
// real names
Player res = game.getPlayerList().stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.filter(player -> player.getName().equals(needName))
.findFirst()
.orElse(null);
// test names - cheat commands will be compatible in both modes (quick test and normal)
if (res == null) {
switch (needName.toLowerCase(Locale.ENGLISH)) {
case "me":
case "human":
case "human 1":
res = feedbackPlayer;
break;
case "opponent":
case "opponent 1":
case "computer":
case "computer 1": // multiplayer game uses Computer 2+ naming
case "ai":
case "ai 1":
// try AI
res = game.getPlayerList().stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.filter(Player::isInGame)
.filter(Player::isComputer)
.findFirst()
.orElse(null);
if (res == null) {
// try opponent (human only games)
res = game.getOpponents(feedbackPlayer.getId(), true).stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.filter(Player::isInGame)
.findFirst()
.orElse(null);
}
break;
default:
// raise error message due unknown player name
break;
}
}
return res;
}
public static String sanitize(String input) {

View file

@ -27,11 +27,13 @@ import mage.counters.Counter;
import mage.counters.CounterType;
import mage.designations.Designation;
import mage.filter.FilterMana;
import mage.game.ControllableOrOwnerable;
import mage.game.Game;
import mage.game.command.Dungeon;
import mage.game.command.Emblem;
import mage.game.command.Plane;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.Token;
import mage.game.stack.Spell;
@ -115,7 +117,7 @@ public class CardView extends SimpleCardView {
protected List<String> rightSplitRules;
protected String rightSplitTypeLine;
protected boolean isModalDoubleFacedCard;
protected boolean isDoubleFacedCard;
protected ArtRect artRect = ArtRect.NORMAL;
@ -237,7 +239,7 @@ public class CardView extends SimpleCardView {
this.rightSplitRules = cardView.rightSplitRules == null ? null : new ArrayList<>(cardView.rightSplitRules);
this.rightSplitTypeLine = cardView.rightSplitTypeLine;
this.isModalDoubleFacedCard = cardView.isModalDoubleFacedCard;
this.isDoubleFacedCard = cardView.isDoubleFacedCard;
this.artRect = cardView.artRect;
this.targets = cardView.targets == null ? null : new ArrayList<>(cardView.targets);
@ -427,12 +429,18 @@ public class CardView extends SimpleCardView {
this.manaCostLeftStr = splitCard.getLeftHalfCard().getManaCostSymbols();
this.manaCostRightStr = splitCard.getRightHalfCard().getManaCostSymbols();
} else if (card instanceof ModalDoubleFacedCard) {
this.isModalDoubleFacedCard = true;
ModalDoubleFacedCard mainCard = ((ModalDoubleFacedCard) card);
this.isDoubleFacedCard = true;
DoubleFacedCard mainCard = ((DoubleFacedCard) card);
fullCardName = mainCard.getLeftHalfCard().getName() + MockCard.MODAL_DOUBLE_FACES_NAME_SEPARATOR + mainCard.getRightHalfCard().getName();
this.manaCostLeftStr = mainCard.getLeftHalfCard().getManaCostSymbols();
this.manaCostRightStr = mainCard.getRightHalfCard().getManaCostSymbols();
} else if (card instanceof CardWithSpellOption) {
} else if (card instanceof TransformingDoubleFacedCard) {
this.isDoubleFacedCard = true;
DoubleFacedCard mainCard = ((DoubleFacedCard) card);
fullCardName = mainCard.getLeftHalfCard().getName() + MockCard.MODAL_DOUBLE_FACES_NAME_SEPARATOR + mainCard.getRightHalfCard().getName();
this.manaCostLeftStr = mainCard.getLeftHalfCard().getManaCostSymbols();
this.manaCostRightStr = new ArrayList<>();
} else if (card instanceof CardWithSpellOption) {
this.isSplitCard = true;
CardWithSpellOption mainCard = ((CardWithSpellOption) card);
leftSplitName = mainCard.getName();
@ -530,13 +538,21 @@ public class CardView extends SimpleCardView {
this.extraDeckCard = card.isExtraDeckCard();
// TODO: can probably remove this after tdfc rework
// transformable, double faces cards
this.transformable = card.isTransformable();
if (!(sourceCard.getMainCard() instanceof DoubleFacedCard)) {
this.transformable = card.isTransformable();
Card secondSideCard = card.getSecondCardFace();
if (secondSideCard != null) {
Card secondSideCard = card.getSecondCardFace();
if (secondSideCard != null) {
this.secondCardFace = new CardView(secondSideCard, game);
this.alternateName = secondCardFace.getName();
}
} else if (card instanceof PermanentCard && card.isTransformable()) {
this.transformable = card.isTransformable();
Card secondSideCard = (Card) ((PermanentCard) card).getOtherFace();
this.secondCardFace = new CardView(secondSideCard, game);
this.alternateName = secondCardFace.getName();
this.alternateName = secondSideCard.getName();
}
this.flipCard = card.isFlipCard();
@ -544,11 +560,11 @@ public class CardView extends SimpleCardView {
this.alternateName = card.getFlipCardName();
}
if (card instanceof ModalDoubleFacedCard) {
if (card instanceof DoubleFacedCard) {
this.transformable = true; // enable GUI day/night button
ModalDoubleFacedCard mdfCard = (ModalDoubleFacedCard) card;
this.secondCardFace = new CardView(mdfCard.getRightHalfCard(), game);
this.alternateName = mdfCard.getRightHalfCard().getName();
DoubleFacedCard doubleFacedCard = (DoubleFacedCard) card;
this.secondCardFace = new CardView(doubleFacedCard.getRightHalfCard(), game);
this.alternateName = doubleFacedCard.getRightHalfCard().getName();
}
Card meldsToCard = card.getMeldsToCard();
@ -764,7 +780,11 @@ public class CardView extends SimpleCardView {
String info;
MageObject targetObject = game.getObject(t);
if (targetObject != null) {
info = targetObject.getIdName();
Player player = null;
if (targetObject instanceof ControllableOrOwnerable) {
player = game.getPlayer(((ControllableOrOwnerable) targetObject).getControllerOrOwnerId());
}
info = (player == null ? "" : player.getName() + ": ") + targetObject.getIdName();
} else {
Player targetPlayer = game.getPlayer(t);
if (targetPlayer != null) {

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-counter-plugin</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-plugins</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-reports</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-server-console</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-deck-constructed</artifactId>

View file

@ -27,6 +27,7 @@ public abstract class AbstractCommander extends Constructed {
private static List<CommanderValidator> validators = Arrays.asList(
PartnerValidator.instance,
PartnerVariantValidator.instance,
FriendsForeverValidator.instance,
PartnerWithValidator.instance,
ChooseABackgroundValidator.instance,

View file

@ -44,7 +44,6 @@ public class DuelCommander extends Commander {
banned.add("Library of Alexandria");
banned.add("Lion's Eye Diamond");
banned.add("Lotus Petal");
banned.add("Loyal Retainers");
banned.add("Lutri, the Spellchaser");
banned.add("Maddening Hex");
banned.add("Mana Crypt");
@ -93,8 +92,6 @@ public class DuelCommander extends Commander {
bannedCommander.add("Ajani, Nacatl Pariah");
bannedCommander.add("Arahbo, Roar of the World");
bannedCommander.add("Asmoranomardicadaistinaculdacar");
bannedCommander.add("Baral, Chief of Compliance");
bannedCommander.add("Breya, Etherium Shaper");
bannedCommander.add("Derevi, Empyrial Tactician");
bannedCommander.add("Dihada, Binder of Wills");
@ -102,7 +99,6 @@ public class DuelCommander extends Commander {
bannedCommander.add("Edric, Spymaster of Trest");
bannedCommander.add("Emry, Lurker of the Loch");
bannedCommander.add("Eris, Roar of the Storm");
bannedCommander.add("Esior, Wardwing Familiar");
bannedCommander.add("Ezio Auditore da Firenze");
bannedCommander.add("Geist of Saint Traft");
bannedCommander.add("Inalla, Archmage Ritualist");
@ -116,7 +112,6 @@ public class DuelCommander extends Commander {
bannedCommander.add("Omnath, Locus of Creation");
bannedCommander.add("Prime Speaker Vannifar");
bannedCommander.add("Raffine, Scheming Seer");
bannedCommander.add("Rofellos, Llanowar Emissary");
bannedCommander.add("Shorikai, Genesis Engine");
bannedCommander.add("Tamiyo, Inquisitive Student");
bannedCommander.add("Tasigur, the Golden Fang");

View file

@ -32,6 +32,7 @@ public class Legacy extends Constructed {
banned.add("Dig Through Time");
banned.add("Dreadhorde Arcanist");
banned.add("Earthcraft");
banned.add("Entomb");
banned.add("Fastbond");
banned.add("Flash");
banned.add("Frantic Search");
@ -56,6 +57,7 @@ public class Legacy extends Constructed {
banned.add("Mox Ruby");
banned.add("Mox Sapphire");
banned.add("Mystical Tutor");
banned.add("Nadu, Winged Wisdom");
banned.add("Necropotence");
banned.add("Oath of Druids");
banned.add("Oko, Thief of Crowns");

View file

@ -46,6 +46,7 @@ public class Pauper extends Constructed {
banned.add("Gitaxian Probe");
banned.add("Grapeshot");
banned.add("Gush");
banned.add("High Tide");
banned.add("Hymn to Tourach");
banned.add("Invigorate");
banned.add("Kuldotha Rebirth");

View file

@ -30,6 +30,7 @@ public class Pioneer extends Constructed {
banned.add("Field of the Dead");
banned.add("Flooded Strand");
banned.add("Geological Appraiser");
banned.add("Heartfire Hero");
banned.add("Inverter of Truth");
banned.add("Jegantha, the Wellspring");
banned.add("Karn, the Great Creator");

View file

@ -24,8 +24,11 @@ public class Standard extends Constructed {
banned.add("Heartfire Hero");
banned.add("Hopeless Nightmare");
banned.add("Monstrous Rage");
banned.add("Proft's Eidetic Memory");
banned.add("Screaming Nemesis");
banned.add("This Town Ain't Big Enough");
banned.add("Up the Beanstalk");
banned.add("Vivi Ornitier");
}
static List<String> makeLegalSets() {

View file

@ -206,9 +206,9 @@ public class TinyLeaders extends Constructed {
if (card instanceof SplitCard) {
costs.add(((SplitCard) card).getLeftHalfCard().getManaValue());
costs.add(((SplitCard) card).getRightHalfCard().getManaValue());
} else if (card instanceof ModalDoubleFacedCard) {
costs.add(((ModalDoubleFacedCard) card).getLeftHalfCard().getManaValue());
costs.add(((ModalDoubleFacedCard) card).getRightHalfCard().getManaValue());
} else if (card instanceof DoubleFacedCard) {
costs.add(((DoubleFacedCard) card).getLeftHalfCard().getManaValue());
costs.add(((DoubleFacedCard) card).getRightHalfCard().getManaValue());
} else {
costs.add(card.getManaValue());
}

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-deck-limited</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-brawlduel</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-brawlfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-canadianhighlanderduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-commanderduel</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-commanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-custompillaroftheparunsduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-freeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-freeformcommanderduel</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-freeformcommanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-freeformunlimitedcommander</artifactId>
@ -23,7 +23,7 @@
<dependency>
<groupId>org.mage</groupId>
<artifactId>mage-game-freeformcommanderfreeforall</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
<scope>compile</scope>
</dependency>
</dependencies>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-momirduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-momirfreeforall</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-oathbreakerduel</artifactId>
@ -22,7 +22,7 @@
<dependency>
<groupId>org.mage</groupId>
<artifactId>mage-game-oathbreakerfreeforall</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
<scope>compile</scope>
</dependency>
</dependencies>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-oathbreakerfreeforall</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-pennydreadfulcommanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-tinyleadersduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-game-twoplayerduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-player-ai-draftbot</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-player-ai-ma</artifactId>

View file

@ -502,7 +502,7 @@ public class ComputerPlayer6 extends ComputerPlayer {
}
logger.warn("Possible freeze chain:");
if (root != null && chain.isEmpty()) {
logger.warn(" - unknown use case (too many possible targets?)"); // maybe can't finish any calc, maybe related to target options, I don't know
logger.warn(" - unknown use case (too many possible targets?)"); // maybe can't finish any calc, maybe related to target options
}
chain.forEach(s -> {
logger.warn(" - " + s);

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-player-ai</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-player-ai-mcts</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-player-human</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-tournament-boosterdraft</artifactId>

View file

@ -15,411 +15,455 @@ public class PauperCube extends DraftCube {
public PauperCube() {
super("The Pauper Cube", "", 2025, 5, 7);
cubeCards.add(new CardIdentity("Academy Journeymage", ""));
cubeCards.add(new CardIdentity("Act of Treason", ""));
cubeCards.add(new CardIdentity("Adventuring Gear", ""));
cubeCards.add(new CardIdentity("Aerie Bowmasters", ""));
cubeCards.add(new CardIdentity("Aerie Ouphes", ""));
cubeCards.add(new CardIdentity("Aether Adept", ""));
cubeCards.add(new CardIdentity("Abrade", ""));
cubeCards.add(new CardIdentity("Abraded Bluffs", ""));
cubeCards.add(new CardIdentity("Abundant Harvest", ""));
cubeCards.add(new CardIdentity("Accursed Marauder", ""));
cubeCards.add(new CardIdentity("Aerie Auxiliary", ""));
cubeCards.add(new CardIdentity("Aether Chaser", ""));
cubeCards.add(new CardIdentity("Aether Poisoner", ""));
cubeCards.add(new CardIdentity("Aethersnipe", ""));
cubeCards.add(new CardIdentity("Agony Warp", ""));
cubeCards.add(new CardIdentity("Ambush Viper", ""));
cubeCards.add(new CardIdentity("Angelic Purge", ""));
cubeCards.add(new CardIdentity("Arachnus Web", ""));
cubeCards.add(new CardIdentity("Arc Lightning", ""));
cubeCards.add(new CardIdentity("Armillary Sphere", ""));
cubeCards.add(new CardIdentity("Arrest", ""));
cubeCards.add(new CardIdentity("Ash Barrens", ""));
cubeCards.add(new CardIdentity("Ainok Bond-Kin", ""));
cubeCards.add(new CardIdentity("Alabaster Host Intercessor", ""));
cubeCards.add(new CardIdentity("Ambitious Assault", ""));
cubeCards.add(new CardIdentity("Ancestral Blade", ""));
cubeCards.add(new CardIdentity("Annoyed Altisaur", ""));
cubeCards.add(new CardIdentity("Arbor Elf", ""));
cubeCards.add(new CardIdentity("Archaeomancer", ""));
cubeCards.add(new CardIdentity("Ardent Elementalist", ""));
cubeCards.add(new CardIdentity("Ardenvale Tactician", ""));
cubeCards.add(new CardIdentity("Armadillo Cloak", ""));
cubeCards.add(new CardIdentity("Arms of Hadar", ""));
cubeCards.add(new CardIdentity("Ashes to Ashes", ""));
cubeCards.add(new CardIdentity("Assault Zeppelid", ""));
cubeCards.add(new CardIdentity("Attended Knight", ""));
cubeCards.add(new CardIdentity("Auger Spree", ""));
cubeCards.add(new CardIdentity("Augur of Bolas", ""));
cubeCards.add(new CardIdentity("Aven Riftwatcher", ""));
cubeCards.add(new CardIdentity("Aven Surveyor", ""));
cubeCards.add(new CardIdentity("Azorius Guildgate", ""));
cubeCards.add(new CardIdentity("Baloth Gorger", ""));
cubeCards.add(new CardIdentity("Barbed Lightning", ""));
cubeCards.add(new CardIdentity("Basking Rootwalla", ""));
cubeCards.add(new CardIdentity("Azorius Chancery", ""));
cubeCards.add(new CardIdentity("Bannerhide Krushok", ""));
cubeCards.add(new CardIdentity("Barbed Batterfist", ""));
cubeCards.add(new CardIdentity("Basilica Screecher", ""));
cubeCards.add(new CardIdentity("Basilisk Gate", ""));
cubeCards.add(new CardIdentity("Basking Broodscale", ""));
cubeCards.add(new CardIdentity("Battle Screech", ""));
cubeCards.add(new CardIdentity("Beetleback Chief", ""));
cubeCards.add(new CardIdentity("Beetleform Mage", ""));
cubeCards.add(new CardIdentity("Beneath the Sands", ""));
cubeCards.add(new CardIdentity("Behold the Multiverse", ""));
cubeCards.add(new CardIdentity("Blastoderm", ""));
cubeCards.add(new CardIdentity("Blazing Torch", ""));
cubeCards.add(new CardIdentity("Blessed Hippogriff", ""));
cubeCards.add(new CardIdentity("Blightning", ""));
cubeCards.add(new CardIdentity("Blinding Beam", ""));
cubeCards.add(new CardIdentity("Blink of an Eye", ""));
cubeCards.add(new CardIdentity("Bloodfell Caves", ""));
cubeCards.add(new CardIdentity("Blossoming Sands", ""));
cubeCards.add(new CardIdentity("Bonded Construct", ""));
cubeCards.add(new CardIdentity("Bonds of Faith", ""));
cubeCards.add(new CardIdentity("Blood Fountain", ""));
cubeCards.add(new CardIdentity("Bloodwater Entity", ""));
cubeCards.add(new CardIdentity("Bloom Hulk", ""));
cubeCards.add(new CardIdentity("Body Dropper", ""));
cubeCards.add(new CardIdentity("Bogardan Dragonheart", ""));
cubeCards.add(new CardIdentity("Bonder's Ornament", ""));
cubeCards.add(new CardIdentity("Bone Picker", ""));
cubeCards.add(new CardIdentity("Bonesplitter", ""));
cubeCards.add(new CardIdentity("Boros Guildgate", ""));
cubeCards.add(new CardIdentity("Boros Elite", ""));
cubeCards.add(new CardIdentity("Boros Garrison", ""));
cubeCards.add(new CardIdentity("Borrowed Grace", ""));
cubeCards.add(new CardIdentity("Botanical Plaza", ""));
cubeCards.add(new CardIdentity("Bountiful Landscape", ""));
cubeCards.add(new CardIdentity("Brainstorm", ""));
cubeCards.add(new CardIdentity("Bramble Wurm", ""));
cubeCards.add(new CardIdentity("Branching Bolt", ""));
cubeCards.add(new CardIdentity("Brazen Wolves", ""));
cubeCards.add(new CardIdentity("Bristling Backwoods", ""));
cubeCards.add(new CardIdentity("Bubble Snare", ""));
cubeCards.add(new CardIdentity("Burning-Tree Emissary", ""));
cubeCards.add(new CardIdentity("Burst Lightning", ""));
cubeCards.add(new CardIdentity("Butcher Ghoul", ""));
cubeCards.add(new CardIdentity("Cage of Hands", ""));
cubeCards.add(new CardIdentity("Calcite Snapper", ""));
cubeCards.add(new CardIdentity("Call of the Conclave", ""));
cubeCards.add(new CardIdentity("Call the Cavalry", ""));
cubeCards.add(new CardIdentity("Bushwhack", ""));
cubeCards.add(new CardIdentity("Candy Grapple", ""));
cubeCards.add(new CardIdentity("Candy Trail", ""));
cubeCards.add(new CardIdentity("Capsize", ""));
//cubeCards.add(new CardIdentity("Carnivorous Death-Parrot", ""));
cubeCards.add(new CardIdentity("Cartouche of Strength", ""));
cubeCards.add(new CardIdentity("Captured by Lagacs", ""));
cubeCards.add(new CardIdentity("Carnophage", ""));
cubeCards.add(new CardIdentity("Carrier Thrall", ""));
cubeCards.add(new CardIdentity("Carrion Feeder", ""));
cubeCards.add(new CardIdentity("Cartouche of Solidarity", ""));
cubeCards.add(new CardIdentity("Cast Down", ""));
cubeCards.add(new CardIdentity("Cathar Commando", ""));
cubeCards.add(new CardIdentity("Cavern Harpy", ""));
cubeCards.add(new CardIdentity("Centaur Healer", ""));
cubeCards.add(new CardIdentity("Chain Lightning", ""));
cubeCards.add(new CardIdentity("Chainer's Edict", ""));
//cubeCards.add(new CardIdentity("Chivalrous Chevalier", ""));
cubeCards.add(new CardIdentity("Cinder Barrens", ""));
cubeCards.add(new CardIdentity("Citanul Woodreaders", ""));
cubeCards.add(new CardIdentity("Claustrophobia", ""));
cubeCards.add(new CardIdentity("Clay Statue", ""));
cubeCards.add(new CardIdentity("Cloaked Siren", ""));
cubeCards.add(new CardIdentity("Clutch of Currents", ""));
cubeCards.add(new CardIdentity("Chitin Gravestalker", ""));
cubeCards.add(new CardIdentity("Cindering Cutthroat", ""));
cubeCards.add(new CardIdentity("Clawing Torment", ""));
cubeCards.add(new CardIdentity("Clockwork Percussionist", ""));
cubeCards.add(new CardIdentity("Cloudkin Seer", ""));
cubeCards.add(new CardIdentity("Coalition Honor Guard", ""));
//cubeCards.add(new CardIdentity("Cogwork Librarian", ""));
cubeCards.add(new CardIdentity("Colossal Might", ""));
//cubeCards.add(new CardIdentity("Common Iguana", ""));
cubeCards.add(new CardIdentity("Coiling Oracle", ""));
cubeCards.add(new CardIdentity("Colossal Dreadmask", ""));
cubeCards.add(new CardIdentity("Combat Professor", ""));
cubeCards.add(new CardIdentity("Compulsive Research", ""));
cubeCards.add(new CardIdentity("Compulsory Rest", ""));
cubeCards.add(new CardIdentity("Consume Strength", ""));
cubeCards.add(new CardIdentity("Corrupted Zendikon", ""));
cubeCards.add(new CardIdentity("Conclave Naturalists", ""));
cubeCards.add(new CardIdentity("Condescend", ""));
cubeCards.add(new CardIdentity("Conduit Goblin", ""));
cubeCards.add(new CardIdentity("Conduit Pylons", ""));
cubeCards.add(new CardIdentity("Consider", ""));
cubeCards.add(new CardIdentity("Contagious Vorrac", ""));
cubeCards.add(new CardIdentity("Contaminated Landscape", ""));
cubeCards.add(new CardIdentity("Counterspell", ""));
cubeCards.add(new CardIdentity("Court Hussar", ""));
cubeCards.add(new CardIdentity("Crippling Fatigue", ""));
cubeCards.add(new CardIdentity("Cruel Witness", ""));
cubeCards.add(new CardIdentity("Crypt Rats", ""));
cubeCards.add(new CardIdentity("Crystallization", ""));
cubeCards.add(new CardIdentity("Cunning Strike", ""));
cubeCards.add(new CardIdentity("Curse of Chains", ""));
cubeCards.add(new CardIdentity("Custodi Squire", ""));
cubeCards.add(new CardIdentity("Daring Skyjek", ""));
cubeCards.add(new CardIdentity("Dauntless Cathar", ""));
cubeCards.add(new CardIdentity("Dead Reveler", ""));
cubeCards.add(new CardIdentity("Dead Weight", ""));
cubeCards.add(new CardIdentity("Deadeye Tormentor", ""));
cubeCards.add(new CardIdentity("Dark-Dweller Oracle", ""));
cubeCards.add(new CardIdentity("Dauntless Unity", ""));
cubeCards.add(new CardIdentity("Dauthi Horror", ""));
cubeCards.add(new CardIdentity("Dauthi Slayer", ""));
cubeCards.add(new CardIdentity("Death Denied", ""));
cubeCards.add(new CardIdentity("Deathbloom Thallid", ""));
cubeCards.add(new CardIdentity("Deceptive Landscape", ""));
cubeCards.add(new CardIdentity("Deep Analysis", ""));
cubeCards.add(new CardIdentity("Deprive", ""));
cubeCards.add(new CardIdentity("Depths of Desire", ""));
cubeCards.add(new CardIdentity("Deputy of Acquittals", ""));
cubeCards.add(new CardIdentity("Deftblade Elite", ""));
cubeCards.add(new CardIdentity("Deranged Assistant", ""));
cubeCards.add(new CardIdentity("Desecrator Hag", ""));
cubeCards.add(new CardIdentity("Desert", ""));
cubeCards.add(new CardIdentity("Devour Flesh", ""));
cubeCards.add(new CardIdentity("Diabolic Edict", ""));
cubeCards.add(new CardIdentity("Dimir Guildgate", ""));
cubeCards.add(new CardIdentity("Dimir Aqueduct", ""));
cubeCards.add(new CardIdentity("Dimir Guildmage", ""));
cubeCards.add(new CardIdentity("Dinrova Horror", ""));
cubeCards.add(new CardIdentity("Disfigure", ""));
cubeCards.add(new CardIdentity("Dismal Backwater", ""));
cubeCards.add(new CardIdentity("Disowned Ancestor", ""));
cubeCards.add(new CardIdentity("Displace", ""));
cubeCards.add(new CardIdentity("Dog Umbra", ""));
cubeCards.add(new CardIdentity("Dog Walker", ""));
cubeCards.add(new CardIdentity("Doom Blade", ""));
cubeCards.add(new CardIdentity("Doomed Traveler", ""));
cubeCards.add(new CardIdentity("Dragon Fodder", ""));
cubeCards.add(new CardIdentity("Dusk Legion Zealot", ""));
cubeCards.add(new CardIdentity("Dynacharge", ""));
cubeCards.add(new CardIdentity("Eager Construct", ""));
cubeCards.add(new CardIdentity("Eldrazi Devastator", ""));
cubeCards.add(new CardIdentity("Dread Return", ""));
cubeCards.add(new CardIdentity("Dreg Mangler", ""));
cubeCards.add(new CardIdentity("Eagles of the North", ""));
cubeCards.add(new CardIdentity("Ecstatic Awakener", ""));
cubeCards.add(new CardIdentity("Eldrazi Repurposer", ""));
cubeCards.add(new CardIdentity("Eldrazi Skyspawner", ""));
cubeCards.add(new CardIdentity("Elephant Ambush", ""));
cubeCards.add(new CardIdentity("Elephant Guide", ""));
cubeCards.add(new CardIdentity("Elite Vanguard", ""));
cubeCards.add(new CardIdentity("Emperor Crocodile", ""));
cubeCards.add(new CardIdentity("Epic Confrontation", ""));
cubeCards.add(new CardIdentity("Errant Ephemeron", ""));
cubeCards.add(new CardIdentity("Evincar's Justice", ""));
cubeCards.add(new CardIdentity("Evolving Wilds", ""));
//cubeCards.add(new CardIdentity("Extremely Slow Zombie", ""));
cubeCards.add(new CardIdentity("Elvish Mystic", ""));
cubeCards.add(new CardIdentity("Ephemerate", ""));
cubeCards.add(new CardIdentity("Eroded Canyon", ""));
cubeCards.add(new CardIdentity("Escape Tunnel", ""));
cubeCards.add(new CardIdentity("Evolution Witness", ""));
cubeCards.add(new CardIdentity("Exclude", ""));
cubeCards.add(new CardIdentity("Experiment One", ""));
cubeCards.add(new CardIdentity("Faceless Butcher", ""));
cubeCards.add(new CardIdentity("Faerie Guidemother", ""));
cubeCards.add(new CardIdentity("Faerie Seer", ""));
cubeCards.add(new CardIdentity("Faith's Fetters", ""));
cubeCards.add(new CardIdentity("Faithful Watchdog", ""));
cubeCards.add(new CardIdentity("Falkenrath Noble", ""));
cubeCards.add(new CardIdentity("Fanatical Firebrand", ""));
cubeCards.add(new CardIdentity("Feeling of Dread", ""));
cubeCards.add(new CardIdentity("Fervent Cathar", ""));
cubeCards.add(new CardIdentity("Farseek", ""));
cubeCards.add(new CardIdentity("Feed the Swarm", ""));
cubeCards.add(new CardIdentity("Feign Death", ""));
cubeCards.add(new CardIdentity("Fertile Ground", ""));
cubeCards.add(new CardIdentity("Filigree Familiar", ""));
cubeCards.add(new CardIdentity("Fireball", ""));
cubeCards.add(new CardIdentity("Fireblade Artist", ""));
cubeCards.add(new CardIdentity("Fireblast", ""));
cubeCards.add(new CardIdentity("Firebolt", ""));
cubeCards.add(new CardIdentity("Firebrand Archer", ""));
cubeCards.add(new CardIdentity("Fireslinger", ""));
cubeCards.add(new CardIdentity("First-Sphere Gargantua", ""));
cubeCards.add(new CardIdentity("Flame Slash", ""));
cubeCards.add(new CardIdentity("Flayer Husk", ""));
cubeCards.add(new CardIdentity("Flurry of Horns", ""));
cubeCards.add(new CardIdentity("Forked Bolt", ""));
cubeCards.add(new CardIdentity("Forsaken Sanctuary", ""));
cubeCards.add(new CardIdentity("Fortify", ""));
cubeCards.add(new CardIdentity("Foul Orchard", ""));
cubeCards.add(new CardIdentity("Forbidden Friendship", ""));
cubeCards.add(new CardIdentity("Foreboding Landscape", ""));
cubeCards.add(new CardIdentity("Frenzied Goblin", ""));
cubeCards.add(new CardIdentity("Frilled Deathspitter", ""));
cubeCards.add(new CardIdentity("Frilled Oculus", ""));
cubeCards.add(new CardIdentity("Frostburn Weird", ""));
cubeCards.add(new CardIdentity("Fungal Infection", ""));
cubeCards.add(new CardIdentity("GO TO JAIL", ""));
cubeCards.add(new CardIdentity("Gathan Raiders", ""));
cubeCards.add(new CardIdentity("Gather the Townsfolk", ""));
cubeCards.add(new CardIdentity("Ghirapur Gearcrafter", ""));
cubeCards.add(new CardIdentity("Frost Trickster", ""));
cubeCards.add(new CardIdentity("Galvanic Discharge", ""));
cubeCards.add(new CardIdentity("Generous Ent", ""));
cubeCards.add(new CardIdentity("Geyser Drake", ""));
cubeCards.add(new CardIdentity("Ghostly Flicker", ""));
cubeCards.add(new CardIdentity("Giant Growth", ""));
cubeCards.add(new CardIdentity("Gideon's Lawkeeper", ""));
cubeCards.add(new CardIdentity("Glint-Sleeve Artisan", ""));
cubeCards.add(new CardIdentity("Gnawing Zombie", ""));
cubeCards.add(new CardIdentity("Goblin Freerunner", ""));
cubeCards.add(new CardIdentity("Goblin Heelcutter", ""));
cubeCards.add(new CardIdentity("Goblin Trailblazer", ""));
cubeCards.add(new CardIdentity("Gift of Fangs", ""));
cubeCards.add(new CardIdentity("Gift of Orzhova", ""));
cubeCards.add(new CardIdentity("Gingerbrute", ""));
cubeCards.add(new CardIdentity("Gitaxian Probe", ""));
cubeCards.add(new CardIdentity("Gixian Infiltrator", ""));
cubeCards.add(new CardIdentity("Glimmerlight", ""));
cubeCards.add(new CardIdentity("Gnarlid Colony", ""));
cubeCards.add(new CardIdentity("Gnawing Crescendo", ""));
cubeCards.add(new CardIdentity("Go for the Throat", ""));
cubeCards.add(new CardIdentity("Goblin Anarchomancer", ""));
cubeCards.add(new CardIdentity("Goblin Bushwhacker", ""));
cubeCards.add(new CardIdentity("Goblin Electromancer", ""));
cubeCards.add(new CardIdentity("Goblin Motivator", ""));
cubeCards.add(new CardIdentity("Goblin Surprise", ""));
cubeCards.add(new CardIdentity("Gods Willing", ""));
cubeCards.add(new CardIdentity("Goldmeadow Harrier", ""));
cubeCards.add(new CardIdentity("Golgari Guildgate", ""));
cubeCards.add(new CardIdentity("Golgari Rot Farm", ""));
cubeCards.add(new CardIdentity("Grapple with the Past", ""));
cubeCards.add(new CardIdentity("Grasping Scoundrel", ""));
cubeCards.add(new CardIdentity("Gravedigger", ""));
cubeCards.add(new CardIdentity("Gray Merchant of Asphodel", ""));
cubeCards.add(new CardIdentity("Grim Contest", ""));
cubeCards.add(new CardIdentity("Grisly Salvage", ""));
cubeCards.add(new CardIdentity("Grixis Slavedriver", ""));
cubeCards.add(new CardIdentity("Gruul Guildgate", ""));
cubeCards.add(new CardIdentity("Gryff Vanguard", ""));
cubeCards.add(new CardIdentity("Guardian Automaton", ""));
cubeCards.add(new CardIdentity("Greater Tanuki", ""));
cubeCards.add(new CardIdentity("Greatsword of Tyr", ""));
cubeCards.add(new CardIdentity("Grim Bauble", ""));
cubeCards.add(new CardIdentity("Grim Initiate", ""));
cubeCards.add(new CardIdentity("Growth Spiral", ""));
cubeCards.add(new CardIdentity("Gruul Turf", ""));
cubeCards.add(new CardIdentity("Guardian Idol", ""));
cubeCards.add(new CardIdentity("Guardian of the Guildpact", ""));
cubeCards.add(new CardIdentity("Guildsworn Prowler", ""));
cubeCards.add(new CardIdentity("Gurmag Angler", ""));
cubeCards.add(new CardIdentity("Halimar Wavewatch", ""));
cubeCards.add(new CardIdentity("Harrow", ""));
cubeCards.add(new CardIdentity("Harsh Sustenance", ""));
cubeCards.add(new CardIdentity("Highland Lake", ""));
cubeCards.add(new CardIdentity("Guttersnipe", ""));
cubeCards.add(new CardIdentity("Hard Evidence", ""));
cubeCards.add(new CardIdentity("Harried Spearguard", ""));
cubeCards.add(new CardIdentity("Haunted Fengraf", ""));
cubeCards.add(new CardIdentity("Haunted Mire", ""));
cubeCards.add(new CardIdentity("Hazard of the Dunes", ""));
cubeCards.add(new CardIdentity("Heliod's Pilgrim", ""));
cubeCards.add(new CardIdentity("Hickory Woodlot", ""));
cubeCards.add(new CardIdentity("Hidden Grotto", ""));
cubeCards.add(new CardIdentity("Hissing Iguanar", ""));
cubeCards.add(new CardIdentity("Hobblefiend", ""));
cubeCards.add(new CardIdentity("Holy Cow", ""));
cubeCards.add(new CardIdentity("Hooting Mandrills", ""));
cubeCards.add(new CardIdentity("Hordeling Outburst", ""));
cubeCards.add(new CardIdentity("Imperiosaur", ""));
cubeCards.add(new CardIdentity("Inner-Flame Acolyte", ""));
cubeCards.add(new CardIdentity("Insolent Neonate", ""));
cubeCards.add(new CardIdentity("Horrific Assault", ""));
cubeCards.add(new CardIdentity("Imperial Oath", ""));
cubeCards.add(new CardIdentity("Improvised Club", ""));
cubeCards.add(new CardIdentity("Impulse", ""));
cubeCards.add(new CardIdentity("Incinerate", ""));
cubeCards.add(new CardIdentity("Infestation Sage", ""));
cubeCards.add(new CardIdentity("Infuse with Vitality", ""));
cubeCards.add(new CardIdentity("Inspiring Overseer", ""));
cubeCards.add(new CardIdentity("Inspiring Paladin", ""));
cubeCards.add(new CardIdentity("Into the Roil", ""));
cubeCards.add(new CardIdentity("Isolation Zone", ""));
cubeCards.add(new CardIdentity("Ivy Elemental", ""));
cubeCards.add(new CardIdentity("Izzet Chronarch", ""));
cubeCards.add(new CardIdentity("Izzet Guildgate", ""));
cubeCards.add(new CardIdentity("Iron Apprentice", ""));
cubeCards.add(new CardIdentity("Izzet Boilerworks", ""));
cubeCards.add(new CardIdentity("Izzet Charm", ""));
cubeCards.add(new CardIdentity("Jackal Pup", ""));
cubeCards.add(new CardIdentity("Jilt", ""));
cubeCards.add(new CardIdentity("Jade Avenger", ""));
cubeCards.add(new CardIdentity("Jade Guardian", ""));
cubeCards.add(new CardIdentity("Jagged Barrens", ""));
cubeCards.add(new CardIdentity("Jewel Thief", ""));
cubeCards.add(new CardIdentity("Jhessian Thief", ""));
cubeCards.add(new CardIdentity("Journey to Nowhere", ""));
cubeCards.add(new CardIdentity("Jungle Hollow", ""));
cubeCards.add(new CardIdentity("Jungleborn Pioneer", ""));
cubeCards.add(new CardIdentity("Keldon Marauders", ""));
cubeCards.add(new CardIdentity("Keldon Overseer", ""));
cubeCards.add(new CardIdentity("Keldon Raider", ""));
cubeCards.add(new CardIdentity("Judge's Familiar", ""));
cubeCards.add(new CardIdentity("Juggernaut", ""));
cubeCards.add(new CardIdentity("Kingpin's Pet", ""));
cubeCards.add(new CardIdentity("Kitesail Corsair", ""));
cubeCards.add(new CardIdentity("Kor Skyfisher", ""));
cubeCards.add(new CardIdentity("Kozilek's Channeler", ""));
cubeCards.add(new CardIdentity("Krenko's Command", ""));
cubeCards.add(new CardIdentity("Krosan Tusker", ""));
cubeCards.add(new CardIdentity("Lash Out", ""));
cubeCards.add(new CardIdentity("Last Gasp", ""));
cubeCards.add(new CardIdentity("Leave in the Dust", ""));
cubeCards.add(new CardIdentity("Lead the Stampede", ""));
cubeCards.add(new CardIdentity("Legion Vanguard", ""));
cubeCards.add(new CardIdentity("Leonin Bola", ""));
cubeCards.add(new CardIdentity("Lifecraft Cavalry", ""));
cubeCards.add(new CardIdentity("Lightning Bolt", ""));
cubeCards.add(new CardIdentity("Liliana's Specter", ""));
cubeCards.add(new CardIdentity("Loyal Pegasus", ""));
//cubeCards.add(new CardIdentity("Lurking Automaton", ""));
cubeCards.add(new CardIdentity("Magma Jet", ""));
cubeCards.add(new CardIdentity("Makeshift Mauler", ""));
cubeCards.add(new CardIdentity("Lightning Strike", ""));
cubeCards.add(new CardIdentity("Llanowar Elves", ""));
cubeCards.add(new CardIdentity("Llanowar Visionary", ""));
cubeCards.add(new CardIdentity("Loathsome Curator", ""));
cubeCards.add(new CardIdentity("Longstalk Brawl", ""));
cubeCards.add(new CardIdentity("Looter il-Kor", ""));
cubeCards.add(new CardIdentity("Lorehold Campus", ""));
cubeCards.add(new CardIdentity("Lorien Revealed", ""));
cubeCards.add(new CardIdentity("Lose Focus", ""));
cubeCards.add(new CardIdentity("Lyev Skyknight", ""));
cubeCards.add(new CardIdentity("Malevolent Rumble", ""));
cubeCards.add(new CardIdentity("Man-o'-War", ""));
cubeCards.add(new CardIdentity("Mana Leak", ""));
cubeCards.add(new CardIdentity("Mardu Hordechief", ""));
cubeCards.add(new CardIdentity("Mana Tithe", ""));
cubeCards.add(new CardIdentity("Mandibular Kite", ""));
cubeCards.add(new CardIdentity("Mardu Skullhunter", ""));
cubeCards.add(new CardIdentity("Martyr of Dusk", ""));
cubeCards.add(new CardIdentity("Maul Splicer", ""));
cubeCards.add(new CardIdentity("Maze of Ith", ""));
cubeCards.add(new CardIdentity("Meandering River", ""));
cubeCards.add(new CardIdentity("Mental Note", ""));
cubeCards.add(new CardIdentity("Midnight Scavengers", ""));
cubeCards.add(new CardIdentity("Massive Might", ""));
cubeCards.add(new CardIdentity("Mayhem Patrol", ""));
cubeCards.add(new CardIdentity("Merfolk Looter", ""));
cubeCards.add(new CardIdentity("Militia Bugler", ""));
cubeCards.add(new CardIdentity("Mind Stone", ""));
cubeCards.add(new CardIdentity("Minotaur Skullcleaver", ""));
cubeCards.add(new CardIdentity("Miner's Guidewing", ""));
cubeCards.add(new CardIdentity("Mire Triton", ""));
cubeCards.add(new CardIdentity("Mirrorshell Crab", ""));
cubeCards.add(new CardIdentity("Miscalculation", ""));
cubeCards.add(new CardIdentity("Mishra's Factory", ""));
cubeCards.add(new CardIdentity("Mist Raven", ""));
cubeCards.add(new CardIdentity("Mistral Charger", ""));
cubeCards.add(new CardIdentity("Mobile Garrison", ""));
cubeCards.add(new CardIdentity("Mogg Fanatic", ""));
cubeCards.add(new CardIdentity("Mogg Flunkies", ""));
cubeCards.add(new CardIdentity("Mistral Singer", ""));
cubeCards.add(new CardIdentity("Mocking Sprite", ""));
cubeCards.add(new CardIdentity("Mogg War Marshal", ""));
cubeCards.add(new CardIdentity("Moldervine Cloak", ""));
cubeCards.add(new CardIdentity("Molten Gatekeeper", ""));
cubeCards.add(new CardIdentity("Momentary Blink", ""));
cubeCards.add(new CardIdentity("Morgue Theft", ""));
cubeCards.add(new CardIdentity("Monastery Swiftspear", ""));
cubeCards.add(new CardIdentity("Monstrous Emergence", ""));
cubeCards.add(new CardIdentity("Moon-Circuit Hacker", ""));
cubeCards.add(new CardIdentity("Mother Bear", ""));
cubeCards.add(new CardIdentity("Mulldrifter", ""));
cubeCards.add(new CardIdentity("Nameless Inversion", ""));
cubeCards.add(new CardIdentity("Narcolepsy", ""));
cubeCards.add(new CardIdentity("Nessian Asp", ""));
cubeCards.add(new CardIdentity("Nest Robber", ""));
cubeCards.add(new CardIdentity("Nezumi Cutthroat", ""));
cubeCards.add(new CardIdentity("Murmuring Mystic", ""));
cubeCards.add(new CardIdentity("Mutagenic Growth", ""));
cubeCards.add(new CardIdentity("Mystic Sanctuary", ""));
cubeCards.add(new CardIdentity("Nature's Lore", ""));
cubeCards.add(new CardIdentity("Nest Invader", ""));
cubeCards.add(new CardIdentity("Nested Shambler", ""));
cubeCards.add(new CardIdentity("Nezumi Linkbreaker", ""));
cubeCards.add(new CardIdentity("Night Market", ""));
cubeCards.add(new CardIdentity("Night's Whisper", ""));
cubeCards.add(new CardIdentity("Nightscape Familiar", ""));
cubeCards.add(new CardIdentity("Ninja of the Deep Hours", ""));
cubeCards.add(new CardIdentity("Novice Inspector", ""));
cubeCards.add(new CardIdentity("Nyxborn Hydra", ""));
cubeCards.add(new CardIdentity("Oblivion Ring", ""));
cubeCards.add(new CardIdentity("Oona's Grace", ""));
//cubeCards.add(new CardIdentity("Ordinary Pony", ""));
cubeCards.add(new CardIdentity("Orzhov Guildgate", ""));
cubeCards.add(new CardIdentity("Otherworldly Journey", ""));
cubeCards.add(new CardIdentity("Overgrown Armasaur", ""));
cubeCards.add(new CardIdentity("Pacifism", ""));
cubeCards.add(new CardIdentity("Paladin of the Bloodstained", ""));
cubeCards.add(new CardIdentity("Peema Outrider", ""));
cubeCards.add(new CardIdentity("Penumbra Spider", ""));
cubeCards.add(new CardIdentity("Okiba-Gang Shinobi", ""));
cubeCards.add(new CardIdentity("Oliphaunt", ""));
cubeCards.add(new CardIdentity("Opt", ""));
cubeCards.add(new CardIdentity("Orcish Hellraiser", ""));
cubeCards.add(new CardIdentity("Orzhov Basilica", ""));
cubeCards.add(new CardIdentity("Owlbear", ""));
cubeCards.add(new CardIdentity("Palace Sentinels", ""));
cubeCards.add(new CardIdentity("Pegasus Guardian", ""));
cubeCards.add(new CardIdentity("Peregrine Drake", ""));
cubeCards.add(new CardIdentity("Perilous Landscape", ""));
cubeCards.add(new CardIdentity("Perilous Myr", ""));
cubeCards.add(new CardIdentity("Pestermite", ""));
cubeCards.add(new CardIdentity("Pestilence", ""));
cubeCards.add(new CardIdentity("Petrify", ""));
cubeCards.add(new CardIdentity("Phantom Interference", ""));
cubeCards.add(new CardIdentity("Phantom Nomad", ""));
cubeCards.add(new CardIdentity("Phantom Tiger", ""));
cubeCards.add(new CardIdentity("Phyrexian Rager", ""));
cubeCards.add(new CardIdentity("Pillory of the Sleepless", ""));
cubeCards.add(new CardIdentity("Pit Fight", ""));
cubeCards.add(new CardIdentity("Pit Keeper", ""));
cubeCards.add(new CardIdentity("Plated Geopede", ""));
cubeCards.add(new CardIdentity("Plagued Rusalka", ""));
cubeCards.add(new CardIdentity("Planar Disruption", ""));
cubeCards.add(new CardIdentity("Ponder", ""));
cubeCards.add(new CardIdentity("Porcelain Legionnaire", ""));
cubeCards.add(new CardIdentity("Pounce", ""));
cubeCards.add(new CardIdentity("Predatory Nightstalker", ""));
cubeCards.add(new CardIdentity("Preening Champion", ""));
cubeCards.add(new CardIdentity("Preordain", ""));
cubeCards.add(new CardIdentity("Prey Upon", ""));
cubeCards.add(new CardIdentity("Prismari Campus", ""));
cubeCards.add(new CardIdentity("Prismatic Strands", ""));
cubeCards.add(new CardIdentity("Pristine Talisman", ""));
cubeCards.add(new CardIdentity("Prophetic Prism", ""));
cubeCards.add(new CardIdentity("Pulse of Murasa", ""));
cubeCards.add(new CardIdentity("Pursue Glory", ""));
cubeCards.add(new CardIdentity("Putrid Goblin", ""));
cubeCards.add(new CardIdentity("Putrid Leech", ""));
cubeCards.add(new CardIdentity("Pyrotechnics", ""));
cubeCards.add(new CardIdentity("Qasali Pridemage", ""));
cubeCards.add(new CardIdentity("Quandrix Campus", ""));
cubeCards.add(new CardIdentity("Quandrix Pledgemage", ""));
cubeCards.add(new CardIdentity("Quick Study", ""));
cubeCards.add(new CardIdentity("Quicksand", ""));
cubeCards.add(new CardIdentity("Racers' Ring", ""));
cubeCards.add(new CardIdentity("Radiant Grove", ""));
cubeCards.add(new CardIdentity("Raffine's Informant", ""));
cubeCards.add(new CardIdentity("Raid Bombardment", ""));
cubeCards.add(new CardIdentity("Raise the Alarm", ""));
cubeCards.add(new CardIdentity("Rakdos Guildgate", ""));
cubeCards.add(new CardIdentity("Rakdos Carnarium", ""));
cubeCards.add(new CardIdentity("Rally at the Hornburg", ""));
cubeCards.add(new CardIdentity("Rally the Peasants", ""));
cubeCards.add(new CardIdentity("Rampant Growth", ""));
cubeCards.add(new CardIdentity("Ram Through", ""));
cubeCards.add(new CardIdentity("Rancor", ""));
cubeCards.add(new CardIdentity("Ranger's Guile", ""));
cubeCards.add(new CardIdentity("Ray of Command", ""));
cubeCards.add(new CardIdentity("Razorfin Hunter", ""));
cubeCards.add(new CardIdentity("Ransack the Lab", ""));
cubeCards.add(new CardIdentity("Reckless Charge", ""));
cubeCards.add(new CardIdentity("Recoil", ""));
//cubeCards.add(new CardIdentity("Regicide", ""));
cubeCards.add(new CardIdentity("Reckless Impulse", ""));
cubeCards.add(new CardIdentity("Red Herring", ""));
cubeCards.add(new CardIdentity("Remove Soul", ""));
cubeCards.add(new CardIdentity("Rend Flesh", ""));
cubeCards.add(new CardIdentity("Rendclaw Trow", ""));
cubeCards.add(new CardIdentity("Renegade Freighter", ""));
cubeCards.add(new CardIdentity("Repeal", ""));
cubeCards.add(new CardIdentity("Retrofitted Transmogrant", ""));
cubeCards.add(new CardIdentity("Rhox Veteran", ""));
cubeCards.add(new CardIdentity("Rift Bolt", ""));
cubeCards.add(new CardIdentity("Rishadan Airship", ""));
cubeCards.add(new CardIdentity("Rugged Highlands", ""));
cubeCards.add(new CardIdentity("Runed Servitor", ""));
cubeCards.add(new CardIdentity("Rushing River", ""));
cubeCards.add(new CardIdentity("Ruthless Ripper", ""));
cubeCards.add(new CardIdentity("Sailor of Means", ""));
cubeCards.add(new CardIdentity("Rimrock Knight", ""));
cubeCards.add(new CardIdentity("Rolling Thunder", ""));
cubeCards.add(new CardIdentity("Safehold Elite", ""));
cubeCards.add(new CardIdentity("Sakura-Tribe Elder", ""));
cubeCards.add(new CardIdentity("Sandsteppe Outcast", ""));
cubeCards.add(new CardIdentity("Sangrite Backlash", ""));
cubeCards.add(new CardIdentity("Saproling Migration", ""));
cubeCards.add(new CardIdentity("Sarkhan's Rage", ""));
cubeCards.add(new CardIdentity("Savage Punch", ""));
cubeCards.add(new CardIdentity("Sarulf's Packmate", ""));
cubeCards.add(new CardIdentity("Savannah Lions", ""));
cubeCards.add(new CardIdentity("Scatter the Seeds", ""));
cubeCards.add(new CardIdentity("Scion Summoner", ""));
cubeCards.add(new CardIdentity("Scion of the Wild", ""));
cubeCards.add(new CardIdentity("Scholar of Combustion", ""));
cubeCards.add(new CardIdentity("Scorched Rusalka", ""));
cubeCards.add(new CardIdentity("Scoured Barrens", ""));
cubeCards.add(new CardIdentity("Scourge Devil", ""));
cubeCards.add(new CardIdentity("Screeching Skaab", ""));
cubeCards.add(new CardIdentity("Scuzzback Marauders", ""));
cubeCards.add(new CardIdentity("Search for Tomorrow", ""));
cubeCards.add(new CardIdentity("Searing Blaze", ""));
cubeCards.add(new CardIdentity("Seeker of Insight", ""));
cubeCards.add(new CardIdentity("Scrapwork Mutt", ""));
cubeCards.add(new CardIdentity("Scurrilous Sentry", ""));
cubeCards.add(new CardIdentity("Search Party Captain", ""));
cubeCards.add(new CardIdentity("Searing Spear", ""));
cubeCards.add(new CardIdentity("Seeker of the Way", ""));
cubeCards.add(new CardIdentity("Selesnya Guildgate", ""));
//cubeCards.add(new CardIdentity("Selfie Preservation", ""));
cubeCards.add(new CardIdentity("Separatist Voidmage", ""));
cubeCards.add(new CardIdentity("Seraph of Dawn", ""));
cubeCards.add(new CardIdentity("Sergeant-at-Arms", ""));
cubeCards.add(new CardIdentity("Seething Landscape", ""));
cubeCards.add(new CardIdentity("Selesnya Sanctuary", ""));
cubeCards.add(new CardIdentity("Serrated Arrows", ""));
cubeCards.add(new CardIdentity("Shaper Parasite", ""));
cubeCards.add(new CardIdentity("Sheer Drop", ""));
cubeCards.add(new CardIdentity("Shelter", ""));
cubeCards.add(new CardIdentity("Shimmering Glasskite", ""));
cubeCards.add(new CardIdentity("Sigil Blessing", ""));
cubeCards.add(new CardIdentity("Silent Departure", ""));
cubeCards.add(new CardIdentity("Simic Guildgate", ""));
cubeCards.add(new CardIdentity("Skirk Marauder", ""));
cubeCards.add(new CardIdentity("Skyknight Legionnaire", ""));
cubeCards.add(new CardIdentity("Slash Panther", ""));
cubeCards.add(new CardIdentity("Snakeform", ""));
cubeCards.add(new CardIdentity("Serum Visionary", ""));
cubeCards.add(new CardIdentity("Serum Visions", ""));
cubeCards.add(new CardIdentity("Settle Beyond Reality", ""));
cubeCards.add(new CardIdentity("Shardless Outlander", ""));
cubeCards.add(new CardIdentity("Shattered Landscape", ""));
cubeCards.add(new CardIdentity("Sheltering Landscape", ""));
cubeCards.add(new CardIdentity("Shipwreck Dowser", ""));
cubeCards.add(new CardIdentity("Silver Drake", ""));
cubeCards.add(new CardIdentity("Silverback Shaman", ""));
cubeCards.add(new CardIdentity("Silverquill Campus", ""));
cubeCards.add(new CardIdentity("Simic Growth Chamber", ""));
cubeCards.add(new CardIdentity("Skewer the Critics", ""));
cubeCards.add(new CardIdentity("Skybridge Towers", ""));
cubeCards.add(new CardIdentity("Snakeskin Veil", ""));
cubeCards.add(new CardIdentity("Snap", ""));
cubeCards.add(new CardIdentity("Snapping Voidcraw", ""));
cubeCards.add(new CardIdentity("Soltari Trooper", ""));
cubeCards.add(new CardIdentity("Soul Manipulation", ""));
cubeCards.add(new CardIdentity("Soul of the Rapids", ""));
cubeCards.add(new CardIdentity("Soulstinger", ""));
cubeCards.add(new CardIdentity("Sparring Construct", ""));
cubeCards.add(new CardIdentity("Sphere of the Suns", ""));
cubeCards.add(new CardIdentity("Spike Jester", ""));
//cubeCards.add(new CardIdentity("Squirrel Dealer", ""));
cubeCards.add(new CardIdentity("Staggershock", ""));
cubeCards.add(new CardIdentity("Star Compass", ""));
cubeCards.add(new CardIdentity("Stitched Drake", ""));
cubeCards.add(new CardIdentity("Stone Quarry", ""));
cubeCards.add(new CardIdentity("Storm Fleet Pyromancer", ""));
cubeCards.add(new CardIdentity("Spelleater Wolverine", ""));
cubeCards.add(new CardIdentity("Sprout Swarm", ""));
cubeCards.add(new CardIdentity("Stormfront Pegasus", ""));
cubeCards.add(new CardIdentity("Stormscape Apprentice", ""));
cubeCards.add(new CardIdentity("Strip Mine", ""));
cubeCards.add(new CardIdentity("Striped Riverwinder", ""));
cubeCards.add(new CardIdentity("Stronghold Confessor", ""));
cubeCards.add(new CardIdentity("Submerged Boneyard", ""));
cubeCards.add(new CardIdentity("Sultai Scavenger", ""));
cubeCards.add(new CardIdentity("Suppression Bonds", ""));
cubeCards.add(new CardIdentity("Swiftwater Cliffs", ""));
cubeCards.add(new CardIdentity("Sylvan Might", ""));
cubeCards.add(new CardIdentity("Sylvok Lifestaff", ""));
cubeCards.add(new CardIdentity("Temporal Isolation", ""));
cubeCards.add(new CardIdentity("Tenement Crasher", ""));
cubeCards.add(new CardIdentity("Terminate", ""));
cubeCards.add(new CardIdentity("Terramorphic Expanse", ""));
cubeCards.add(new CardIdentity("Sulfurous Blast", ""));
cubeCards.add(new CardIdentity("Sunlance", ""));
cubeCards.add(new CardIdentity("Suture Priest", ""));
cubeCards.add(new CardIdentity("Sword Coast Serpent", ""));
cubeCards.add(new CardIdentity("Syndic of Tithes", ""));
cubeCards.add(new CardIdentity("Tamiyo's Safekeeping", ""));
cubeCards.add(new CardIdentity("Tangled Islet", ""));
cubeCards.add(new CardIdentity("Teetering Peaks", ""));
cubeCards.add(new CardIdentity("Tempest Angler", ""));
cubeCards.add(new CardIdentity("Tenth District Legionnaire", ""));
cubeCards.add(new CardIdentity("Thorn of the Black Rose", ""));
cubeCards.add(new CardIdentity("Thornweald Archer", ""));
cubeCards.add(new CardIdentity("Thornwood Falls", ""));
cubeCards.add(new CardIdentity("Thought Scour", ""));
cubeCards.add(new CardIdentity("Thraben Charm", ""));
cubeCards.add(new CardIdentity("Thraben Inspector", ""));
cubeCards.add(new CardIdentity("Thrill-Kill Assassin", ""));
cubeCards.add(new CardIdentity("Thundering Giant", ""));
cubeCards.add(new CardIdentity("Thunderous Wrath", ""));
cubeCards.add(new CardIdentity("Timber Gorge", ""));
cubeCards.add(new CardIdentity("Time to Feed", ""));
cubeCards.add(new CardIdentity("Thriving Grubs", ""));
cubeCards.add(new CardIdentity("Thriving Skyclaw", ""));
cubeCards.add(new CardIdentity("Tithe Drinker", ""));
cubeCards.add(new CardIdentity("Totem-Guide Hartebeest", ""));
cubeCards.add(new CardIdentity("Tithing Blade", ""));
cubeCards.add(new CardIdentity("Tocasia's Dig Site", ""));
cubeCards.add(new CardIdentity("Tolarian Terror", ""));
cubeCards.add(new CardIdentity("Topan Freeblade", ""));
cubeCards.add(new CardIdentity("Tortured Existence", ""));
cubeCards.add(new CardIdentity("Tragic Slip", ""));
cubeCards.add(new CardIdentity("Tramway Station", ""));
cubeCards.add(new CardIdentity("Tranquil Cove", ""));
cubeCards.add(new CardIdentity("Tranquil Expanse", ""));
cubeCards.add(new CardIdentity("Travel Preparations", ""));
cubeCards.add(new CardIdentity("Tranquil Landscape", ""));
cubeCards.add(new CardIdentity("Trapped in the Screen", ""));
cubeCards.add(new CardIdentity("Treasure Cruise", ""));
cubeCards.add(new CardIdentity("Treetop Snarespinner", ""));
cubeCards.add(new CardIdentity("Triplicate Spirits", ""));
cubeCards.add(new CardIdentity("Typhoid Rats", ""));
cubeCards.add(new CardIdentity("Troll of Khazad-dum", ""));
cubeCards.add(new CardIdentity("Trumpeting Herd", ""));
cubeCards.add(new CardIdentity("Tuskeri Firewalker", ""));
cubeCards.add(new CardIdentity("Tuskguard Captain", ""));
cubeCards.add(new CardIdentity("Twisted Landscape", ""));
cubeCards.add(new CardIdentity("Ulamog's Crusher", ""));
cubeCards.add(new CardIdentity("Ulvenwald Captive", ""));
cubeCards.add(new CardIdentity("Unable to Scream", ""));
cubeCards.add(new CardIdentity("Unbounded Potential", ""));
cubeCards.add(new CardIdentity("Underworld Rage-Hound", ""));
cubeCards.add(new CardIdentity("Undying Malice", ""));
cubeCards.add(new CardIdentity("Unearth", ""));
cubeCards.add(new CardIdentity("Unmake", ""));
cubeCards.add(new CardIdentity("Vampire Interloper", ""));
cubeCards.add(new CardIdentity("Unwilling Ingredient", ""));
cubeCards.add(new CardIdentity("Urban Daggertooth", ""));
cubeCards.add(new CardIdentity("Utopia Sprawl", ""));
cubeCards.add(new CardIdentity("Vampire Lacerator", ""));
cubeCards.add(new CardIdentity("Vampire Sovereign", ""));
cubeCards.add(new CardIdentity("Vault Skirge", ""));
cubeCards.add(new CardIdentity("Viashino Firstblade", ""));
cubeCards.add(new CardIdentity("Vendetta", ""));
cubeCards.add(new CardIdentity("Village Rites", ""));
cubeCards.add(new CardIdentity("Vines of Vastwood", ""));
cubeCards.add(new CardIdentity("Voldaren Duelist", ""));
cubeCards.add(new CardIdentity("Vizier of Tumbling Sands", ""));
cubeCards.add(new CardIdentity("Volatile Wanderglyph", ""));
cubeCards.add(new CardIdentity("Voracious Varmint", ""));
cubeCards.add(new CardIdentity("Voracious Vermin", ""));
cubeCards.add(new CardIdentity("Vulshok Morningstar", ""));
cubeCards.add(new CardIdentity("Vulshok Sorcerer", ""));
cubeCards.add(new CardIdentity("Vulturous Aven", ""));
cubeCards.add(new CardIdentity("Wakedancer", ""));
cubeCards.add(new CardIdentity("Walker of the Grove", ""));
cubeCards.add(new CardIdentity("Wall of Roots", ""));
cubeCards.add(new CardIdentity("War Flare", ""));
cubeCards.add(new CardIdentity("Warden of Evos Isle", ""));
cubeCards.add(new CardIdentity("Warped Landscape", ""));
cubeCards.add(new CardIdentity("Warren Pilferers", ""));
cubeCards.add(new CardIdentity("Wasteland Scorpion", ""));
cubeCards.add(new CardIdentity("Waterknot", ""));
cubeCards.add(new CardIdentity("Wary Thespian", ""));
cubeCards.add(new CardIdentity("Waterfront District", ""));
cubeCards.add(new CardIdentity("Wayfarer's Bauble", ""));
cubeCards.add(new CardIdentity("Weakstone's Subjugation", ""));
cubeCards.add(new CardIdentity("Werebear", ""));
cubeCards.add(new CardIdentity("Whitemane Lion", ""));
cubeCards.add(new CardIdentity("Wild Instincts", ""));
cubeCards.add(new CardIdentity("Wild Mongrel", ""));
cubeCards.add(new CardIdentity("Wild Nacatl", ""));
cubeCards.add(new CardIdentity("Wildsize", ""));
cubeCards.add(new CardIdentity("Will-Forged Golem", ""));
cubeCards.add(new CardIdentity("Wind-Scarred Crag", ""));
cubeCards.add(new CardIdentity("Winged Coatl", ""));
cubeCards.add(new CardIdentity("Wojek Halberdiers", ""));
cubeCards.add(new CardIdentity("Woodland Stream", ""));
cubeCards.add(new CardIdentity("Wrecking Ball", ""));
cubeCards.add(new CardIdentity("Wretched Gryff", ""));
cubeCards.add(new CardIdentity("Wild Growth", ""));
cubeCards.add(new CardIdentity("Wildfire Elemental", ""));
cubeCards.add(new CardIdentity("Winding Way", ""));
cubeCards.add(new CardIdentity("Winter Eladrin", ""));
cubeCards.add(new CardIdentity("Witch's Cottage", ""));
cubeCards.add(new CardIdentity("Wither and Bloom", ""));
cubeCards.add(new CardIdentity("Witherbloom Campus", ""));
cubeCards.add(new CardIdentity("Witness Protection", ""));
cubeCards.add(new CardIdentity("Witty Roastmaster", ""));
cubeCards.add(new CardIdentity("Wrangle", ""));
cubeCards.add(new CardIdentity("Wrenn's Resolve", ""));
cubeCards.add(new CardIdentity("Writhing Chrysalis", ""));
cubeCards.add(new CardIdentity("Yavimaya Elder", ""));
cubeCards.add(new CardIdentity("Yavimaya Sapherd", ""));
cubeCards.add(new CardIdentity("Yotian Soldier", ""));
cubeCards.add(new CardIdentity("Yavimaya Steelcrusher", ""));
cubeCards.add(new CardIdentity("You Hear Something on Watch", ""));
cubeCards.add(new CardIdentity("You Meet in a Tavern", ""));
cubeCards.add(new CardIdentity("Young Blue Dragon", ""));
cubeCards.add(new CardIdentity("Zephyr Winder", ""));
}
}

View file

@ -13,8 +13,15 @@ import mage.game.draft.DraftCube;
public class VintageCube extends DraftCube {
public VintageCube() {
super("MTGO Vintage Cube", "", 2025, 4, 23);
super("MTGO Vintage Cube", "", 2025, 10, 1);
//cubeCards.add(new CardIdentity("Ademi of the Silkchutes", ""));
//cubeCards.add(new CardIdentity("Cren, Undercity Dreamer", ""));
//cubeCards.add(new CardIdentity("Goben, Gene-Splice Savant", ""));
//cubeCards.add(new CardIdentity("Makdee and Itla, Skysnarers", ""));
//cubeCards.add(new CardIdentity("Nia, Skysail Storyteller", ""));
//cubeCards.add(new CardIdentity("Spectral Restitching", ""));
//cubeCards.add(new CardIdentity("Walk-In Closet // Forgotten Cellar", ""));
cubeCards.add(new CardIdentity("Abhorrent Oculus", ""));
cubeCards.add(new CardIdentity("Abrade", ""));
cubeCards.add(new CardIdentity("Adeline, Resplendent Cathar", ""));
@ -29,15 +36,18 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Arena of Glory", ""));
cubeCards.add(new CardIdentity("Arid Mesa", ""));
cubeCards.add(new CardIdentity("Arwen, Mortal Queen", ""));
cubeCards.add(new CardIdentity("Astrologian's Planisphere", ""));
cubeCards.add(new CardIdentity("Atraxa, Grand Unifier", ""));
cubeCards.add(new CardIdentity("Avacyn's Pilgrim", ""));
cubeCards.add(new CardIdentity("Badlands", ""));
cubeCards.add(new CardIdentity("Balance", ""));
cubeCards.add(new CardIdentity("Baleful Mastery", ""));
cubeCards.add(new CardIdentity("Baleful Strix", ""));
cubeCards.add(new CardIdentity("Baloth Prime", ""));
cubeCards.add(new CardIdentity("Barrowgoyf", ""));
cubeCards.add(new CardIdentity("Basalt Monolith", ""));
cubeCards.add(new CardIdentity("Bayou", ""));
cubeCards.add(new CardIdentity("Berserk", ""));
cubeCards.add(new CardIdentity("Birds of Paradise", ""));
cubeCards.add(new CardIdentity("Bitter Triumph", ""));
cubeCards.add(new CardIdentity("Black Lotus", ""));
@ -47,15 +57,16 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Blightsteel Colossus", ""));
cubeCards.add(new CardIdentity("Blood Crypt", ""));
cubeCards.add(new CardIdentity("Bloodbraid Challenger", ""));
cubeCards.add(new CardIdentity("Bloodchief's Thirst", ""));
cubeCards.add(new CardIdentity("Bloodstained Mire", ""));
cubeCards.add(new CardIdentity("Bloodtithe Harvester", ""));
cubeCards.add(new CardIdentity("Blooming Marsh", ""));
cubeCards.add(new CardIdentity("Bolas's Citadel", ""));
cubeCards.add(new CardIdentity("Bone Shards", ""));
cubeCards.add(new CardIdentity("Bonecrusher Giant", ""));
cubeCards.add(new CardIdentity("Bonehoard Dracosaur", ""));
cubeCards.add(new CardIdentity("Boseiju, Who Endures", ""));
cubeCards.add(new CardIdentity("Botanical Sanctum", ""));
cubeCards.add(new CardIdentity("Bountiful Landscape", ""));
cubeCards.add(new CardIdentity("Brain Freeze", ""));
cubeCards.add(new CardIdentity("Brainstorm", ""));
cubeCards.add(new CardIdentity("Brainsurge", ""));
@ -71,6 +82,7 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Carnage Interpreter", ""));
cubeCards.add(new CardIdentity("Cathar Commando", ""));
cubeCards.add(new CardIdentity("Caustic Bronco", ""));
cubeCards.add(new CardIdentity("Cecil, Dark Knight", ""));
cubeCards.add(new CardIdentity("Celestial Colonnade", ""));
cubeCards.add(new CardIdentity("Chain Lightning", ""));
cubeCards.add(new CardIdentity("Chain of Smog", ""));
@ -80,25 +92,26 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Chromatic Star", ""));
cubeCards.add(new CardIdentity("Chrome Mox", ""));
cubeCards.add(new CardIdentity("City of Traitors", ""));
cubeCards.add(new CardIdentity("Clarion Conqueror", ""));
cubeCards.add(new CardIdentity("Coalition Relic", ""));
cubeCards.add(new CardIdentity("Collective Brutality", ""));
cubeCards.add(new CardIdentity("Commercial District", ""));
cubeCards.add(new CardIdentity("Concealed Courtyard", ""));
cubeCards.add(new CardIdentity("Concealing Curtains", ""));
cubeCards.add(new CardIdentity("Consider", ""));
cubeCards.add(new CardIdentity("Consult the Star Charts", ""));
cubeCards.add(new CardIdentity("Containment Priest", ""));
cubeCards.add(new CardIdentity("Copperline Gorge", ""));
cubeCards.add(new CardIdentity("Cori-Steel Cutter", ""));
cubeCards.add(new CardIdentity("Corpse Dance", ""));
cubeCards.add(new CardIdentity("Cosmogrand Zenith", ""));
cubeCards.add(new CardIdentity("Council's Judgment", ""));
cubeCards.add(new CardIdentity("Counterspell", ""));
cubeCards.add(new CardIdentity("Courser of Kruphix", ""));
cubeCards.add(new CardIdentity("Coveted Jewel", ""));
cubeCards.add(new CardIdentity("Crabomination", ""));
cubeCards.add(new CardIdentity("Craterhoof Behemoth", ""));
cubeCards.add(new CardIdentity("Creeping Tar Pit", ""));
cubeCards.add(new CardIdentity("Crop Rotation", ""));
cubeCards.add(new CardIdentity("Crucible of Worlds", ""));
cubeCards.add(new CardIdentity("Cryptic Command", ""));
cubeCards.add(new CardIdentity("Currency Converter", ""));
cubeCards.add(new CardIdentity("Cut Down", ""));
@ -122,6 +135,8 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Displacer Kitten", ""));
cubeCards.add(new CardIdentity("Doomsday", ""));
cubeCards.add(new CardIdentity("Dragon's Rage Channeler", ""));
cubeCards.add(new CardIdentity("Dreadhorde Arcanist", ""));
cubeCards.add(new CardIdentity("Duelist of the Mind", ""));
cubeCards.add(new CardIdentity("Duress", ""));
cubeCards.add(new CardIdentity("Eagles of the North", ""));
cubeCards.add(new CardIdentity("Echo of Eons", ""));
@ -133,8 +148,8 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Embereth Shieldbreaker", ""));
cubeCards.add(new CardIdentity("Emperor of Bones", ""));
cubeCards.add(new CardIdentity("Emrakul, the Aeons Torn", ""));
cubeCards.add(new CardIdentity("Emry, Lurker of the Loch", ""));
cubeCards.add(new CardIdentity("Endurance", ""));
cubeCards.add(new CardIdentity("Enduring Curiosity", ""));
cubeCards.add(new CardIdentity("Enduring Innocence", ""));
cubeCards.add(new CardIdentity("Entomb", ""));
cubeCards.add(new CardIdentity("Ephemerate", ""));
@ -159,27 +174,26 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Field of the Dead", ""));
cubeCards.add(new CardIdentity("Fiery Confluence", ""));
cubeCards.add(new CardIdentity("Figure of Destiny", ""));
cubeCards.add(new CardIdentity("Fire // Ice", ""));
cubeCards.add(new CardIdentity("Fire Covenant", ""));
cubeCards.add(new CardIdentity("Fireblast", ""));
cubeCards.add(new CardIdentity("Firebolt", ""));
cubeCards.add(new CardIdentity("Flame Slash", ""));
cubeCards.add(new CardIdentity("Flame of Anor", ""));
cubeCards.add(new CardIdentity("Flash", ""));
cubeCards.add(new CardIdentity("Flickerwisp", ""));
cubeCards.add(new CardIdentity("Flooded Strand", ""));
cubeCards.add(new CardIdentity("Floodpits Drowner", ""));
cubeCards.add(new CardIdentity("Force of Negation", ""));
cubeCards.add(new CardIdentity("Force of Vigor", ""));
cubeCards.add(new CardIdentity("Force of Will", ""));
cubeCards.add(new CardIdentity("Forensic Gadgeteer", ""));
cubeCards.add(new CardIdentity("Forth Eorlingas!", ""));
cubeCards.add(new CardIdentity("Fractured Identity", ""));
cubeCards.add(new CardIdentity("Frantic Search", ""));
cubeCards.add(new CardIdentity("Fury", ""));
cubeCards.add(new CardIdentity("Fyndhorn Elves", ""));
cubeCards.add(new CardIdentity("Gaea's Cradle", ""));
cubeCards.add(new CardIdentity("Galvanic Blast", ""));
cubeCards.add(new CardIdentity("Galvanic Discharge", ""));
cubeCards.add(new CardIdentity("General Ferrous Rokiric", ""));
cubeCards.add(new CardIdentity("Gau, Feral Youth", ""));
cubeCards.add(new CardIdentity("Generous Ent", ""));
cubeCards.add(new CardIdentity("Generous Plunderer", ""));
cubeCards.add(new CardIdentity("Get Lost", ""));
@ -192,9 +206,7 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Goblin Rabblemaster", ""));
cubeCards.add(new CardIdentity("Godless Shrine", ""));
cubeCards.add(new CardIdentity("Goldspan Dragon", ""));
cubeCards.add(new CardIdentity("Golos, Tireless Pilgrim", ""));
cubeCards.add(new CardIdentity("Grave Titan", ""));
cubeCards.add(new CardIdentity("Greasewrench Goblin", ""));
cubeCards.add(new CardIdentity("Green Sun's Zenith", ""));
cubeCards.add(new CardIdentity("Grief", ""));
cubeCards.add(new CardIdentity("Grim Monolith", ""));
@ -208,14 +220,11 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Haywire Mite", ""));
cubeCards.add(new CardIdentity("Headliner Scarlett", ""));
cubeCards.add(new CardIdentity("Hedge Maze", ""));
cubeCards.add(new CardIdentity("Heritage Reclamation", ""));
cubeCards.add(new CardIdentity("Hero of Bladehold", ""));
cubeCards.add(new CardIdentity("Hexdrinker", ""));
cubeCards.add(new CardIdentity("High Tide", ""));
cubeCards.add(new CardIdentity("Horizon Canopy", ""));
cubeCards.add(new CardIdentity("Huatli, Poet of Unity", ""));
cubeCards.add(new CardIdentity("Hullbreacher", ""));
cubeCards.add(new CardIdentity("Hymn to Tourach", ""));
cubeCards.add(new CardIdentity("Icetill Explorer", ""));
cubeCards.add(new CardIdentity("Ignoble Hierarch", ""));
cubeCards.add(new CardIdentity("Imperial Seal", ""));
cubeCards.add(new CardIdentity("Indatha Triome", ""));
@ -223,7 +232,7 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Inquisition of Kozilek", ""));
cubeCards.add(new CardIdentity("Inspiring Vantage", ""));
cubeCards.add(new CardIdentity("Inti, Seneschal of the Sun", ""));
cubeCards.add(new CardIdentity("Intrepid Adversary", ""));
cubeCards.add(new CardIdentity("Invigorate", ""));
cubeCards.add(new CardIdentity("Ivora, Insatiable Heir", ""));
cubeCards.add(new CardIdentity("Jace, Vryn's Prodigy", ""));
cubeCards.add(new CardIdentity("Jace, Wielder of Mysteries", ""));
@ -240,14 +249,15 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Kellan, Planar Trailblazer", ""));
cubeCards.add(new CardIdentity("Ketria Triome", ""));
cubeCards.add(new CardIdentity("Kitesail Freebooter", ""));
cubeCards.add(new CardIdentity("Kitsa, Otterball Elite", ""));
cubeCards.add(new CardIdentity("Knight of the Reliquary", ""));
cubeCards.add(new CardIdentity("Kolaghan's Command", ""));
cubeCards.add(new CardIdentity("Laelia, the Blade Reforged", ""));
cubeCards.add(new CardIdentity("Lavaspur Boots", ""));
cubeCards.add(new CardIdentity("Ledger Shredder", ""));
cubeCards.add(new CardIdentity("Legion Extruder", ""));
cubeCards.add(new CardIdentity("Legolas's Quick Reflexes", ""));
cubeCards.add(new CardIdentity("Leovold, Emissary of Trest", ""));
cubeCards.add(new CardIdentity("Lethal Scheme", ""));
cubeCards.add(new CardIdentity("Leyline Binding", ""));
cubeCards.add(new CardIdentity("Library of Alexandria", ""));
cubeCards.add(new CardIdentity("Life // Death", ""));
@ -260,6 +270,7 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Llanowar Elves", ""));
cubeCards.add(new CardIdentity("Loot, the Pathfinder", ""));
cubeCards.add(new CardIdentity("Loran of the Third Path", ""));
cubeCards.add(new CardIdentity("Lorien Revealed", ""));
cubeCards.add(new CardIdentity("Lose Focus", ""));
cubeCards.add(new CardIdentity("Lotus Cobra", ""));
cubeCards.add(new CardIdentity("Lotus Petal", ""));
@ -267,10 +278,10 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Lurrus of the Dream-Den", ""));
cubeCards.add(new CardIdentity("Lush Portico", ""));
cubeCards.add(new CardIdentity("Lutri, the Spellchaser", ""));
cubeCards.add(new CardIdentity("Lorien Revealed", ""));
cubeCards.add(new CardIdentity("Magda, Brazen Outlaw", ""));
cubeCards.add(new CardIdentity("Malcolm, Alluring Scoundrel", ""));
cubeCards.add(new CardIdentity("Malevolent Rumble", ""));
cubeCards.add(new CardIdentity("Mana Confluence", ""));
cubeCards.add(new CardIdentity("Mana Crypt", ""));
cubeCards.add(new CardIdentity("Mana Drain", ""));
cubeCards.add(new CardIdentity("Mana Leak", ""));
@ -278,12 +289,12 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Mana Vault", ""));
cubeCards.add(new CardIdentity("Manamorphose", ""));
cubeCards.add(new CardIdentity("Manifold Key", ""));
cubeCards.add(new CardIdentity("March of Otherworldly Light", ""));
cubeCards.add(new CardIdentity("Marsh Flats", ""));
cubeCards.add(new CardIdentity("Memory Jar", ""));
cubeCards.add(new CardIdentity("Memory Lapse", ""));
cubeCards.add(new CardIdentity("Metamorphosis Fanatic", ""));
cubeCards.add(new CardIdentity("Meticulous Archive", ""));
cubeCards.add(new CardIdentity("Mightform Harmonizer", ""));
cubeCards.add(new CardIdentity("Mind Stone", ""));
cubeCards.add(new CardIdentity("Mind Twist", ""));
cubeCards.add(new CardIdentity("Mine Collapse", ""));
@ -292,7 +303,7 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Mishra's Bauble", ""));
cubeCards.add(new CardIdentity("Mishra's Workshop", ""));
cubeCards.add(new CardIdentity("Misty Rainforest", ""));
cubeCards.add(new CardIdentity("Monastery Mentor", ""));
cubeCards.add(new CardIdentity("Monstrous Rage", ""));
cubeCards.add(new CardIdentity("Mother of Runes", ""));
cubeCards.add(new CardIdentity("Mox Diamond", ""));
cubeCards.add(new CardIdentity("Mox Emerald", ""));
@ -301,19 +312,18 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Mox Pearl", ""));
cubeCards.add(new CardIdentity("Mox Ruby", ""));
cubeCards.add(new CardIdentity("Mox Sapphire", ""));
cubeCards.add(new CardIdentity("Multiversal Passage", ""));
cubeCards.add(new CardIdentity("Mutagenic Growth", ""));
cubeCards.add(new CardIdentity("Myr Battlesphere", ""));
cubeCards.add(new CardIdentity("Mystic Confluence", ""));
cubeCards.add(new CardIdentity("Mystical Tutor", ""));
cubeCards.add(new CardIdentity("Nadu, Winged Wisdom", ""));
cubeCards.add(new CardIdentity("Narset, Parter of Veils", ""));
cubeCards.add(new CardIdentity("Natural Order", ""));
cubeCards.add(new CardIdentity("Nature's Lore", ""));
cubeCards.add(new CardIdentity("Necromancy", ""));
cubeCards.add(new CardIdentity("Nethergoyf", ""));
cubeCards.add(new CardIdentity("Nettlecyst", ""));
cubeCards.add(new CardIdentity("Nexus of Becoming", ""));
cubeCards.add(new CardIdentity("Night's Whisper", ""));
cubeCards.add(new CardIdentity("Nissa, Ascended Animist", ""));
cubeCards.add(new CardIdentity("Nissa, Who Shakes the World", ""));
cubeCards.add(new CardIdentity("No More Lies", ""));
cubeCards.add(new CardIdentity("Noble Hierarch", ""));
@ -328,12 +338,12 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Orcish Lumberjack", ""));
cubeCards.add(new CardIdentity("Otawara, Soaring City", ""));
cubeCards.add(new CardIdentity("Otharri, Suns' Glory", ""));
cubeCards.add(new CardIdentity("Ouroboroid", ""));
cubeCards.add(new CardIdentity("Oust", ""));
cubeCards.add(new CardIdentity("Overgrown Tomb", ""));
cubeCards.add(new CardIdentity("Overlord of the Balemurk", ""));
cubeCards.add(new CardIdentity("Overlord of the Mistmoors", ""));
cubeCards.add(new CardIdentity("Palace Jailer", ""));
cubeCards.add(new CardIdentity("Palantir of Orthanc", ""));
cubeCards.add(new CardIdentity("Paradoxical Outcome", ""));
cubeCards.add(new CardIdentity("Parallax Wave", ""));
cubeCards.add(new CardIdentity("Path to Exile", ""));
@ -343,8 +353,8 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Phelia, Exuberant Shepherd", ""));
cubeCards.add(new CardIdentity("Phlage, Titan of Fire's Fury", ""));
cubeCards.add(new CardIdentity("Phyrexian Metamorph", ""));
cubeCards.add(new CardIdentity("Phyrexian Revoker", ""));
cubeCards.add(new CardIdentity("Pillage the Bog", ""));
cubeCards.add(new CardIdentity("Plagon, Lord of the Beach", ""));
cubeCards.add(new CardIdentity("Plateau", ""));
cubeCards.add(new CardIdentity("Polluted Delta", ""));
cubeCards.add(new CardIdentity("Ponder", ""));
@ -355,17 +365,15 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Primeval Titan", ""));
cubeCards.add(new CardIdentity("Prismatic Ending", ""));
cubeCards.add(new CardIdentity("Prismatic Vista", ""));
cubeCards.add(new CardIdentity("Proft's Eidetic Memory", ""));
cubeCards.add(new CardIdentity("Psychic Frog", ""));
cubeCards.add(new CardIdentity("Pyrogoyf", ""));
cubeCards.add(new CardIdentity("Pyrokinesis", ""));
cubeCards.add(new CardIdentity("Qarsi Revenant", ""));
cubeCards.add(new CardIdentity("Quantum Riddler", ""));
cubeCards.add(new CardIdentity("Questing Beast", ""));
cubeCards.add(new CardIdentity("Raffine's Tower", ""));
cubeCards.add(new CardIdentity("Raffine, Scheming Seer", ""));
cubeCards.add(new CardIdentity("Ragavan, Nimble Pilferer", ""));
cubeCards.add(new CardIdentity("Rain of Filth", ""));
cubeCards.add(new CardIdentity("Rampaging Raptor", ""));
cubeCards.add(new CardIdentity("Ramunap Excavator", ""));
cubeCards.add(new CardIdentity("Rancor", ""));
cubeCards.add(new CardIdentity("Raucous Theater", ""));
cubeCards.add(new CardIdentity("Raugrin Triome", ""));
cubeCards.add(new CardIdentity("Razorverge Thicket", ""));
@ -374,19 +382,14 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Relic of Sauron", ""));
cubeCards.add(new CardIdentity("Remand", ""));
cubeCards.add(new CardIdentity("Reprieve", ""));
cubeCards.add(new CardIdentity("Restless Vinestalk", ""));
cubeCards.add(new CardIdentity("Retrofitter Foundry", ""));
cubeCards.add(new CardIdentity("Riverpyre Verge", ""));
cubeCards.add(new CardIdentity("Robber of the Rich", ""));
cubeCards.add(new CardIdentity("Rofellos, Llanowar Emissary", ""));
cubeCards.add(new CardIdentity("Sacred Foundry", ""));
cubeCards.add(new CardIdentity("Saheeli, Sublime Artificer", ""));
cubeCards.add(new CardIdentity("Sandstorm Salvager", ""));
cubeCards.add(new CardIdentity("Satya, Aetherflux Genius", ""));
cubeCards.add(new CardIdentity("Savai Triome", ""));
cubeCards.add(new CardIdentity("Savannah", ""));
cubeCards.add(new CardIdentity("Scalding Tarn", ""));
cubeCards.add(new CardIdentity("Scrapwork Mutt", ""));
cubeCards.add(new CardIdentity("Screaming Nemesis", ""));
cubeCards.add(new CardIdentity("Scrubland", ""));
cubeCards.add(new CardIdentity("Scythecat Cub", ""));
@ -394,14 +397,13 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Seasoned Pyromancer", ""));
cubeCards.add(new CardIdentity("Securitron Squadron", ""));
cubeCards.add(new CardIdentity("Sedgemoor Witch", ""));
cubeCards.add(new CardIdentity("Seething Song", ""));
cubeCards.add(new CardIdentity("Sensei's Divining Top", ""));
cubeCards.add(new CardIdentity("Sentinel of the Nameless City", ""));
cubeCards.add(new CardIdentity("Serra Paragon", ""));
cubeCards.add(new CardIdentity("Shadowspear", ""));
cubeCards.add(new CardIdentity("Shadowy Backstreet", ""));
cubeCards.add(new CardIdentity("Shallow Grave", ""));
cubeCards.add(new CardIdentity("Shelldock Isle", ""));
cubeCards.add(new CardIdentity("Sheltering Landscape", ""));
cubeCards.add(new CardIdentity("Sheoldred's Edict", ""));
cubeCards.add(new CardIdentity("Sheoldred, the Apocalypse", ""));
cubeCards.add(new CardIdentity("Shifting Woodland", ""));
@ -411,7 +413,7 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Six", ""));
cubeCards.add(new CardIdentity("Skullclamp", ""));
cubeCards.add(new CardIdentity("Skyclave Apparition", ""));
cubeCards.add(new CardIdentity("Slimefoot and Squee", ""));
cubeCards.add(new CardIdentity("Slickshot Show-Off", ""));
cubeCards.add(new CardIdentity("Smuggler's Copter", ""));
cubeCards.add(new CardIdentity("Snapcaster Mage", ""));
cubeCards.add(new CardIdentity("Sneak Attack", ""));
@ -426,8 +428,8 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Spellseeker", ""));
cubeCards.add(new CardIdentity("Spirebluff Canal", ""));
cubeCards.add(new CardIdentity("Springheart Nantuko", ""));
cubeCards.add(new CardIdentity("Spyglass Siren", ""));
cubeCards.add(new CardIdentity("Staff of the Storyteller", ""));
cubeCards.add(new CardIdentity("Starting Town", ""));
cubeCards.add(new CardIdentity("Static Prison", ""));
cubeCards.add(new CardIdentity("Steam Vents", ""));
cubeCards.add(new CardIdentity("Stern Scolding", ""));
@ -440,7 +442,7 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Sunbaked Canyon", ""));
cubeCards.add(new CardIdentity("Sunbillow Verge", ""));
cubeCards.add(new CardIdentity("Sunfall", ""));
cubeCards.add(new CardIdentity("Sunken Ruins", ""));
cubeCards.add(new CardIdentity("Suplex", ""));
cubeCards.add(new CardIdentity("Sword of the Meek", ""));
cubeCards.add(new CardIdentity("Swords to Plowshares", ""));
cubeCards.add(new CardIdentity("Sylvan Caryatid", ""));
@ -455,7 +457,6 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Tamiyo, Collector of Tales", ""));
cubeCards.add(new CardIdentity("Tamiyo, Inquisitive Student", ""));
cubeCards.add(new CardIdentity("Tarfire", ""));
cubeCards.add(new CardIdentity("Tarmogoyf", ""));
cubeCards.add(new CardIdentity("Tear Asunder", ""));
cubeCards.add(new CardIdentity("Teferi, Hero of Dominaria", ""));
cubeCards.add(new CardIdentity("Teferi, Time Raveler", ""));
@ -463,9 +464,10 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Tendrils of Agony", ""));
cubeCards.add(new CardIdentity("Territorial Kavu", ""));
cubeCards.add(new CardIdentity("Tersa Lightshatter", ""));
cubeCards.add(new CardIdentity("Tezzeret, Cruel Captain", ""));
cubeCards.add(new CardIdentity("Thalia, Guardian of Thraben", ""));
cubeCards.add(new CardIdentity("Thassa's Oracle", ""));
cubeCards.add(new CardIdentity("The Aetherspark", ""));
cubeCards.add(new CardIdentity("The Endstone", ""));
cubeCards.add(new CardIdentity("The Mightstone and Weakstone", ""));
cubeCards.add(new CardIdentity("The One Ring", ""));
cubeCards.add(new CardIdentity("The Wandering Emperor", ""));
@ -479,7 +481,9 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Thraben Inspector", ""));
cubeCards.add(new CardIdentity("Through the Breach", ""));
cubeCards.add(new CardIdentity("Thundering Falls", ""));
cubeCards.add(new CardIdentity("Thundertrap Trainer", ""));
cubeCards.add(new CardIdentity("Tidehollow Sculler", ""));
cubeCards.add(new CardIdentity("Tifa Lockhart", ""));
cubeCards.add(new CardIdentity("Time Spiral", ""));
cubeCards.add(new CardIdentity("Time Walk", ""));
cubeCards.add(new CardIdentity("Time Warp", ""));
@ -492,18 +496,14 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Torsten, Founder of Benalia", ""));
cubeCards.add(new CardIdentity("Touch the Spirit Realm", ""));
cubeCards.add(new CardIdentity("Toxic Deluge", ""));
cubeCards.add(new CardIdentity("Treachery", ""));
cubeCards.add(new CardIdentity("Traveling Chocobo", ""));
cubeCards.add(new CardIdentity("Treasure Cruise", ""));
cubeCards.add(new CardIdentity("Trinket Mage", ""));
cubeCards.add(new CardIdentity("Triplicate Titan", ""));
//cubeCards.add(new CardIdentity("Troll of Khazad-dom", ""));
cubeCards.add(new CardIdentity("Troll of Khazad-dum", ""));
cubeCards.add(new CardIdentity("Tropical Island", ""));
cubeCards.add(new CardIdentity("True-Name Nemesis", ""));
cubeCards.add(new CardIdentity("Trumpeting Carnosaur", ""));
cubeCards.add(new CardIdentity("Tundra", ""));
cubeCards.add(new CardIdentity("Turnabout", ""));
cubeCards.add(new CardIdentity("Twisted Landscape", ""));
cubeCards.add(new CardIdentity("Ugin, Eye of the Storms", ""));
cubeCards.add(new CardIdentity("Ulamog, the Infinite Gyre", ""));
cubeCards.add(new CardIdentity("Ulvenwald Oddity", ""));
cubeCards.add(new CardIdentity("Umezawa's Jitte", ""));
cubeCards.add(new CardIdentity("Undercity Sewers", ""));
@ -513,6 +513,7 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Unearth", ""));
cubeCards.add(new CardIdentity("Unexpectedly Absent", ""));
cubeCards.add(new CardIdentity("Unholy Heat", ""));
cubeCards.add(new CardIdentity("Unruly Krasis", ""));
cubeCards.add(new CardIdentity("Upheaval", ""));
cubeCards.add(new CardIdentity("Urborg, Tomb of Yawgmoth", ""));
cubeCards.add(new CardIdentity("Uro, Titan of Nature's Wrath", ""));
@ -526,10 +527,10 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Verdant Catacombs", ""));
cubeCards.add(new CardIdentity("Vindicate", ""));
cubeCards.add(new CardIdentity("Virtue of Loyalty", ""));
cubeCards.add(new CardIdentity("Vivi Ornitier", ""));
cubeCards.add(new CardIdentity("Voice of Victory", ""));
cubeCards.add(new CardIdentity("Volcanic Island", ""));
cubeCards.add(new CardIdentity("Voldaren Epicure", ""));
//cubeCards.add(new CardIdentity("Walk-In Closet // Forgotten Cellar", ""));
cubeCards.add(new CardIdentity("Walking Ballista", ""));
cubeCards.add(new CardIdentity("Wasteland", ""));
cubeCards.add(new CardIdentity("Wastewood Verge", ""));
@ -544,7 +545,6 @@ public class VintageCube extends DraftCube {
cubeCards.add(new CardIdentity("Witherbloom Apprentice", ""));
cubeCards.add(new CardIdentity("Wooded Foothills", ""));
cubeCards.add(new CardIdentity("Woodfall Primus", ""));
cubeCards.add(new CardIdentity("Worldly Tutor", ""));
cubeCards.add(new CardIdentity("Worldspine Wurm", ""));
cubeCards.add(new CardIdentity("Wrath of God", ""));
cubeCards.add(new CardIdentity("Wrenn and Six", ""));

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-tournament-constructed</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-tournament-sealed</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-server-plugins</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-server</artifactId>
@ -208,7 +208,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.27.1</version>
<version>1.28.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.57</version>
<version>1.4.58</version>
</parent>
<artifactId>mage-sets</artifactId>

View file

@ -0,0 +1,58 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.LessonsInGraveCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AangALotToLearn extends CardImpl {
public AangALotToLearn(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G/W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.AVATAR);
this.subtype.add(SubType.ALLY);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Aang has vigilance as long as there's a Lesson card in your graveyard.
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield),
LessonsInGraveCondition.ONE, "{this} has vigilance as long as there's a Lesson card in your graveyard"
)).addHint(LessonsInGraveCondition.getHint()));
// Whenever another creature you control dies, put a +1/+1 counter on Aang.
this.addAbility(new DiesCreatureTriggeredAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance()),
false, StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL
));
}
private AangALotToLearn(final AangALotToLearn card) {
super(card);
}
@Override
public AangALotToLearn copy() {
return new AangALotToLearn(this);
}
}

View file

@ -1,35 +1,39 @@
package mage.cards.g;
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
*
* @author weirddan455
* @author TheElk801
*/
public class GnarledGrovestrider extends CardImpl {
public final class AangAirNomad extends CardImpl {
public GnarledGrovestrider(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "");
this.subtype.add(SubType.TREEFOLK);
this.color.setGreen(true);
public AangAirNomad(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
// Back half of Dormant Grove
this.nightCard = true;
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.AVATAR);
this.subtype.add(SubType.ALLY);
this.power = new MageInt(5);
this.toughness = new MageInt(4);
this.power = new MageInt(3);
this.toughness = new MageInt(6);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// Other creatures you control have vigilance.
@ -39,12 +43,12 @@ public class GnarledGrovestrider extends CardImpl {
)));
}
private GnarledGrovestrider(final GnarledGrovestrider card) {
private AangAirNomad(final AangAirNomad card) {
super(card);
}
@Override
public GnarledGrovestrider copy() {
return new GnarledGrovestrider(this);
public AangAirNomad copy() {
return new AangAirNomad(this);
}
}

View file

@ -0,0 +1,67 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.OneOrMoreLeaveWithoutDyingTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CountersControllerCount;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.counter.AddCountersPlayersEffect;
import mage.abilities.effects.keyword.AirbendTargetEffect;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.permanent.token.AllyToken;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AangAirbendingMaster extends CardImpl {
private static final DynamicValue xValue = new CountersControllerCount(CounterType.EXPERIENCE);
public AangAirbendingMaster(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.AVATAR);
this.subtype.add(SubType.ALLY);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// When Aang enters, airbend another target creature.
Ability ability = new EntersBattlefieldTriggeredAbility(new AirbendTargetEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE));
this.addAbility(ability);
// Whenever one or more creatures you control leave the battlefield without dying, you get an experience counter.
this.addAbility(new OneOrMoreLeaveWithoutDyingTriggeredAbility(
new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), TargetController.YOU),
StaticFilters.FILTER_CONTROLLED_CREATURES
));
// At the beginning of your upkeep, create a 1/1 white Ally creature token for each experience counter you have.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new AllyToken(), xValue)
.setText("create a 1/1 white Ally creature token for each experience counter you have")));
}
private AangAirbendingMaster(final AangAirbendingMaster card) {
super(card);
}
@Override
public AangAirbendingMaster copy() {
return new AangAirbendingMaster(this);
}
}

View file

@ -0,0 +1,64 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.hint.Hint;
import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.permanent.token.AllyToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AangAndKatara extends CardImpl {
private static final FilterPermanent filter = new FilterControlledPermanent("tapped artifacts and/or creatures you control");
static {
filter.add(TappedPredicate.TAPPED);
filter.add(Predicates.or(
CardType.ARTIFACT.getPredicate(),
CardType.CREATURE.getPredicate()
));
}
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter, null);
private static final Hint hint = new ValueHint("Tapped artifacts and creatures you control", xValue);
public AangAndKatara(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{W}{U}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.AVATAR);
this.subtype.add(SubType.ALLY);
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Whenever Aang and Katara enter or attack, create X 1/1 white Ally creature tokens, where X is the number of tapped artifacts and/or creatures you control.
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new CreateTokenEffect(new AllyToken(), xValue))
.setTriggerPhrase("Whenever {this} enter or attack, ").addHint(hint));
}
private AangAndKatara(final AangAndKatara card) {
super(card);
}
@Override
public AangAndKatara copy() {
return new AangAndKatara(this);
}
}

View file

@ -0,0 +1,89 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.keyword.EarthbendTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.target.common.TargetControlledLandPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AangAtTheCrossroads extends TransformingDoubleFacedCard {
private static final FilterCard filter = new FilterCreatureCard("creature card with mana value 4 or less");
private static final FilterPermanent saviorFilter = new FilterPermanent("land creatures");
static {
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 5));
saviorFilter.add(CardType.LAND.getPredicate());
saviorFilter.add(CardType.CREATURE.getPredicate());
}
public AangAtTheCrossroads(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo,
new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.AVATAR, SubType.ALLY}, "{2}{G}{W}{U}",
"Aang, Destined Savior",
new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.AVATAR, SubType.ALLY}, "");
this.getLeftHalfCard().setPT(3, 3);
this.getRightHalfCard().setPT(4, 4);
// Flying
this.getLeftHalfCard().addAbility(FlyingAbility.getInstance());
// When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.
this.getLeftHalfCard().addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect(
5, 1, filter, PutCards.BATTLEFIELD, PutCards.BOTTOM_RANDOM
)));
// When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.
this.getLeftHalfCard().addAbility(new LeavesBattlefieldAllTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(
new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new TransformSourceEffect())
).setText("transform {this} at the beginning of the next upkeep"), StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL)
.setTriggerPhrase("When another creature you control leaves the battlefield, "));
// Aang, Destined Savior
// Flying
this.getRightHalfCard().addAbility(FlyingAbility.getInstance());
// Land creatures you control have vigilance.
this.getRightHalfCard().addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, saviorFilter
)));
// At the beginning of combat on your turn, earthbend 2.
Ability ability = new BeginningOfCombatTriggeredAbility(new EarthbendTargetEffect(2));
ability.addTarget(new TargetControlledLandPermanent());
this.getRightHalfCard().addAbility(ability);
}
private AangAtTheCrossroads(final AangAtTheCrossroads card) {
super(card);
}
@Override
public AangAtTheCrossroads copy() {
return new AangAtTheCrossroads(this);
}
}

View file

@ -0,0 +1,89 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.WaterbendCost;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.abilities.effects.keyword.AirbendTargetEffect;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ReachAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterSpellOrPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.target.common.TargetSpellOrPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AangSwiftSavior extends TransformingDoubleFacedCard {
private static final FilterSpellOrPermanent filter = new FilterSpellOrPermanent("other target creature or spell");
private static final FilterPermanent laFilter = new FilterControlledCreaturePermanent("tapped creature you control");
static {
}
static {
filter.getPermanentFilter().add(CardType.CREATURE.getPredicate());
filter.getPermanentFilter().add(AnotherPredicate.instance);
laFilter.add(TappedPredicate.TAPPED);
}
public AangSwiftSavior(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo,
new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.AVATAR, SubType.ALLY}, "{1}{W}{U}",
"Aang and La, Ocean's Fury",
new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.AVATAR, SubType.SPIRIT, SubType.ALLY}, "");
this.getLeftHalfCard().setPT(2, 3);
this.getRightHalfCard().setPT(5, 5);
// Flash
this.getLeftHalfCard().addAbility(FlashAbility.getInstance());
// Flying
this.getLeftHalfCard().addAbility(FlyingAbility.getInstance());
// When Aang enters, airbend up to one other target creature or spell.
Ability ability = new EntersBattlefieldTriggeredAbility(new AirbendTargetEffect());
ability.addTarget(new TargetSpellOrPermanent(0, 1, filter, false));
this.getLeftHalfCard().addAbility(ability);
// Waterbend {8}: Transform Aang.
this.getLeftHalfCard().addAbility(new SimpleActivatedAbility(new TransformSourceEffect(), new WaterbendCost(8)));
// Aang and La, Ocean's Fury
// Reach
this.getRightHalfCard().addAbility(ReachAbility.getInstance());
// Trample
this.getRightHalfCard().addAbility(TrampleAbility.getInstance());
// Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control.
this.getRightHalfCard().addAbility(new AttacksTriggeredAbility(new AddCountersAllEffect(CounterType.P1P1.createInstance(), laFilter)).setTriggerPhrase("Whenever {this} attack, "));
}
private AangSwiftSavior(final AangSwiftSavior card) {
super(card);
}
@Override
public AangSwiftSavior copy() {
return new AangSwiftSavior(this);
}
}

View file

@ -0,0 +1,70 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.keyword.AirbendTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterPermanent;
import mage.filter.FilterSpell;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AangTheLastAirbender extends CardImpl {
private static final FilterPermanent filter = new FilterNonlandPermanent("other target nonland permanent");
private static final FilterSpell filter2 = new FilterSpell("a Lesson spell");
static {
filter.add(AnotherPredicate.instance);
filter2.add(SubType.LESSON.getPredicate());
}
public AangTheLastAirbender(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.AVATAR);
this.subtype.add(SubType.ALLY);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Aang enters, airbend up to one other target nonland permanent.
Ability ability = new EntersBattlefieldTriggeredAbility(new AirbendTargetEffect());
ability.addTarget(new TargetPermanent(0, 1, filter));
this.addAbility(ability);
// Whenever you cast a Lesson spell, Aang gains lifelink until end of turn.
this.addAbility(new SpellCastControllerTriggeredAbility(
new GainAbilitySourceEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn), filter2, false
));
}
private AangTheLastAirbender(final AangTheLastAirbender card) {
super(card);
}
@Override
public AangTheLastAirbender copy() {
return new AangTheLastAirbender(this);
}
}

View file

@ -0,0 +1,45 @@
package mage.cards.a;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.BlockingPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AangsDefense extends CardImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent("blocking creature you control");
static {
filter.add(BlockingPredicate.instance);
}
public AangsDefense(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
// Target blocking creature you control gets +2/+2 until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2));
this.getSpellAbility().addTarget(new TargetPermanent(filter));
// Draw a card.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("<br>"));
}
private AangsDefense(final AangsDefense card) {
super(card);
}
@Override
public AangsDefense copy() {
return new AangsDefense(this);
}
}

View file

@ -2,13 +2,13 @@ package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.common.WaterbendCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.WaterbendAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -42,9 +42,9 @@ public final class AangsIceberg extends CardImpl {
this.addAbility(ability);
// Waterbend {3}: Sacrifice this enchantment. If you do, scry 2.
this.addAbility(new WaterbendAbility(new DoIfCostPaid(
this.addAbility(new SimpleActivatedAbility(new DoIfCostPaid(
new ScryEffect(2), new SacrificeSourceCost(), null, false
), new GenericManaCost(3)));
), new WaterbendCost(3)));
}
private AangsIceberg(final AangsIceberg card) {

View file

@ -0,0 +1,64 @@
package mage.cards.a;
import mage.abilities.condition.common.KickedCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.abilities.keyword.KickerAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.target.common.TargetCardAndOrCardInLibrary;
import mage.target.common.TargetCardInLibrary;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AangsJourney extends CardImpl {
private static final Predicate<Card> predicate = Predicates.and(
SuperType.BASIC.getPredicate(),
CardType.LAND.getPredicate()
);
public AangsJourney(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}");
this.subtype.add(SubType.LESSON);
// Kicker {2}
this.addAbility(new KickerAbility("{2}"));
// Search your library for a basic land card. If this spell was kicked, instead search your library for a basic land card and a Shrine card. Reveal those cards, put them into your hand, then shuffle.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new SearchLibraryPutInHandEffect(new TargetCardAndOrCardInLibrary(
predicate, SubType.SHRINE.getPredicate(),
"a basic land card and/or a Shrine card"
), true),
new SearchLibraryPutInHandEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true),
KickedCondition.ONCE, "search your library for a basic land card. If this spell was kicked, " +
"instead search your library for a basic land card and a Shrine card. " +
"Reveal those cards, put them into your hand, then shuffle"
));
// You gain 2 life.
this.getSpellAbility().addEffect(new GainLifeEffect(2).concatBy("<br>"));
}
private AangsJourney(final AangsJourney card) {
super(card);
}
@Override
public AangsJourney copy() {
return new AangsJourney(this);
}
}

View file

@ -1,4 +1,4 @@
package mage.cards.s;
package mage.cards.a;
import mage.MageInt;
import mage.abilities.keyword.LifelinkAbility;
@ -12,28 +12,26 @@ import java.util.UUID;
/**
* @author TheElk801
*/
public final class SeasonedCathar extends CardImpl {
public final class AardvarkSloth extends CardImpl {
public SeasonedCathar(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "");
public AardvarkSloth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.subtype.add(SubType.SLOTH);
this.subtype.add(SubType.BEAST);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
this.color.setWhite(true);
this.nightCard = true;
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
}
private SeasonedCathar(final SeasonedCathar card) {
private AardvarkSloth(final AardvarkSloth card) {
super(card);
}
@Override
public SeasonedCathar copy() {
return new SeasonedCathar(this);
public AardvarkSloth copy() {
return new AardvarkSloth(this);
}
}

View file

@ -0,0 +1,35 @@
package mage.cards.a;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AbandonAttachments extends CardImpl {
public AbandonAttachments(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U/R}");
this.subtype.add(SubType.LESSON);
// You may discard a card. If you do, draw two cards.
this.getSpellAbility().addEffect(new DoIfCostPaid(new DrawCardSourceControllerEffect(2), new DiscardCardCost()));
}
private AbandonAttachments(final AbandonAttachments card) {
super(card);
}
@Override
public AbandonAttachments copy() {
return new AbandonAttachments(this);
}
}

View file

@ -0,0 +1,50 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTappedUnlessAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.common.YouControlABasicLandCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AbandonedAirTemple extends CardImpl {
public AbandonedAirTemple(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// This land enters tapped unless you control a basic land.
this.addAbility(new EntersBattlefieldTappedUnlessAbility(YouControlABasicLandCondition.instance)
.addHint(YouControlABasicLandCondition.getHint()));
// {T}: Add {W}.
this.addAbility(new WhiteManaAbility());
// {3}{W}, {T}: Put a +1/+1 counter on each creature you control.
Ability ability = new SimpleActivatedAbility(new AddCountersAllEffect(
CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE
), new ManaCostsImpl<>("{3}{W}"));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
private AbandonedAirTemple(final AbandonedAirTemple card) {
super(card);
}
@Override
public AbandonedAirTemple copy() {
return new AbandonedAirTemple(this);
}
}

View file

@ -0,0 +1,55 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.dynamicvalue.common.ManaSpentToCastCount;
import mage.abilities.effects.common.CastSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.EntersBattlefieldUnderControlOfOpponentOfChoiceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.PartnerVariantType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.game.permanent.token.CordycepsInfectedToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AbbyMercilessSoldier extends CardImpl {
public AbbyMercilessSoldier(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SURVIVOR);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// When you cast this spell, create a number of 1/1 black Fungus Zombie creature tokens named Cordyceps Infected equal to the amount of mana spent to cast it.
this.addAbility(new CastSourceTriggeredAbility(
new CreateTokenEffect(new CordycepsInfectedToken(), ManaSpentToCastCount.instance)
.setText("create a number of 1/1 black Fungus Zombie creature tokens " +
"named Cordyceps Infected equal to the amount of mana spent to cast it")
));
// Abby enters under the control of an opponent of your choice.
this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldUnderControlOfOpponentOfChoiceEffect()));
// Partner--Survivors
this.addAbility(PartnerVariantType.SURVIVORS.makeAbility());
}
private AbbyMercilessSoldier(final AbbyMercilessSoldier card) {
super(card);
}
@Override
public AbbyMercilessSoldier copy() {
return new AbbyMercilessSoldier(this);
}
}

View file

@ -1,16 +1,16 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.game.Game;
import mage.players.Player;
@ -19,23 +19,26 @@ import java.util.UUID;
/**
* @author fireshoes
*/
public final class AberrantResearcher extends CardImpl {
public final class AberrantResearcher extends TransformingDoubleFacedCard {
public AberrantResearcher(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.INSECT);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
super(ownerId, setInfo,
new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.INSECT}, "{3}{U}",
"Perfected Form",
new CardType[]{CardType.CREATURE}, new SubType[]{SubType.INSECT, SubType.HORROR}, "U");
this.secondSideCardClazz = mage.cards.p.PerfectedForm.class;
this.getLeftHalfCard().setPT(3, 2);
this.getRightHalfCard().setPT(5, 4);
// Flying
this.addAbility(FlyingAbility.getInstance());
this.getLeftHalfCard().addAbility(FlyingAbility.getInstance());
// At the beginning of your upkeep, put the top card of your library into your graveyard. If it's an instant or sorcery card, transform Aberrant Researcher.
this.addAbility(new TransformAbility());
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AberrantResearcherEffect()));
this.getLeftHalfCard().addAbility(new BeginningOfUpkeepTriggeredAbility(new AberrantResearcherEffect()));
// Perfected Form
// Flying
this.getRightHalfCard().addAbility(FlyingAbility.getInstance());
}
private AberrantResearcher(final AberrantResearcher card) {

View file

@ -1,22 +1,17 @@
package mage.cards.a;
import mage.MageInt;
import mage.MageItem;
import mage.MageObject;
import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ProtectionAbility;
import mage.abilities.keyword.ProtectionFromEachOpponentAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import mage.game.Game;
import java.util.Optional;
import java.util.UUID;
/**
@ -40,7 +35,7 @@ public final class AbsoluteVirtue extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// You have protection from each of your opponents.
this.addAbility(new SimpleStaticAbility(new GainAbilityControllerEffect(new AbsoluteVirtueAbility())));
this.addAbility(new SimpleStaticAbility(new GainAbilityControllerEffect(new ProtectionFromEachOpponentAbility())));
}
private AbsoluteVirtue(final AbsoluteVirtue card) {
@ -52,34 +47,3 @@ public final class AbsoluteVirtue extends CardImpl {
return new AbsoluteVirtue(this);
}
}
class AbsoluteVirtueAbility extends ProtectionAbility {
public AbsoluteVirtueAbility() {
super(StaticFilters.FILTER_CARD);
}
private AbsoluteVirtueAbility(final AbsoluteVirtueAbility ability) {
super(ability);
}
@Override
public AbsoluteVirtueAbility copy() {
return new AbsoluteVirtueAbility(this);
}
@Override
public String getRule() {
return "protection from each of your opponents";
}
@Override
public boolean canTarget(MageObject source, Game game) {
return Optional
.ofNullable(source)
.map(MageItem::getId)
.map(game::getControllerId)
.map(uuid -> !game.getOpponents(this.getSourceId()).contains(uuid))
.orElse(true);
}
}

View file

@ -0,0 +1,43 @@
package mage.cards.a;
import mage.abilities.condition.common.LessonsInGraveCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.PutCards;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AccumulateWisdom extends CardImpl {
public AccumulateWisdom(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
this.subtype.add(SubType.LESSON);
// Look at the top three cards of your library. Put one of those cards into your hand and the rest on the bottom of your library in any order. Put each of those cards into your hand instead if there are three or more Lesson cards in your graveyard.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new LookLibraryAndPickControllerEffect(3, 3, PutCards.HAND, PutCards.BOTTOM_ANY),
new LookLibraryAndPickControllerEffect(3, 1, PutCards.HAND, PutCards.BOTTOM_ANY),
LessonsInGraveCondition.THREE, "look at the top three cards of your library. " +
"Put one of those cards into your hand and the rest on the bottom of your library in any order. " +
"Put each of those cards into your hand instead if there are three or more Lesson cards in your graveyard"
));
this.getSpellAbility().addHint(LessonsInGraveCondition.getHint());
}
private AccumulateWisdom(final AccumulateWisdom card) {
super(card);
}
@Override
public AccumulateWisdom copy() {
return new AccumulateWisdom(this);
}
}

View file

@ -1,49 +1,76 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
import mage.cards.CardSetInfo;
import mage.cards.DoubleFacedCardHalf;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
/**
* @author halljared
*/
public final class AccursedWitch extends CardImpl {
public final class AccursedWitch extends TransformingDoubleFacedCard {
private static final FilterCard filter = new FilterCard("spells");
public AccursedWitch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(4);
this.toughness = new MageInt(2);
this.secondSideCardClazz = mage.cards.i.InfectiousCurse.class;
super(ownerId, setInfo,
new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.SHAMAN}, "{3}{B}",
"Infectious Curse",
new CardType[]{CardType.ENCHANTMENT}, new SubType[]{SubType.AURA, SubType.CURSE}, "B");
this.getLeftHalfCard().setPT(4, 2);
// Spells your opponents cast that target Accursed Witch cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(
this.getLeftHalfCard().addAbility(new SimpleStaticAbility(
new SpellsCostModificationThatTargetSourceEffect(-1, filter, TargetController.OPPONENT))
);
// When Accursed Witch dies, return it to the battlefield transformed under your control attached to target opponent.
this.addAbility(new TransformAbility());
Ability ability = new DiesSourceTriggeredAbility(new AccursedWitchReturnTransformedEffect());
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
this.getLeftHalfCard().addAbility(ability);
// Infectious Curse
// Enchant player
TargetPlayer auraTarget = new TargetPlayer();
this.getRightHalfCard().getSpellAbility().addTarget(auraTarget);
this.getRightHalfCard().getSpellAbility().addEffect(new AttachEffect(Outcome.Damage));
this.getRightHalfCard().addAbility(new EnchantAbility(auraTarget));
// Spells you cast that target enchanted player cost {1} less to cast.
this.getRightHalfCard().addAbility(new SimpleStaticAbility(new InfectiousCurseCostReductionEffect()));
// At the beginning of enchanted player's upkeep, that player loses 1 life and you gain 1 life.
Ability upkeepAbility = new BeginningOfUpkeepTriggeredAbility(
TargetController.ENCHANTED, new LoseLifeTargetEffect(1).setText("that player loses 1 life"),
false
);
upkeepAbility.addEffect(new GainLifeEffect(1).concatBy("and"));
this.getRightHalfCard().addAbility(upkeepAbility);
}
private AccursedWitch(final AccursedWitch card) {
@ -80,16 +107,67 @@ class AccursedWitchReturnTransformedEffect extends OneShotEffect {
return false;
}
Card card = game.getCard(source.getSourceId());
DoubleFacedCardHalf card = (DoubleFacedCardHalf) game.getCard(source.getSourceId());
if (card == null) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
game.getState().setValue("attachTo:" + source.getSourceId(), attachTo.getId());
game.getState().setValue("attachTo:" + card.getOtherSide().getId(), attachTo.getId());
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
attachTo.addAttachment(card.getId(), source, game);
attachTo.addAttachment(card.getOtherSide().getId(), source, game);
}
return true;
}
}
class InfectiousCurseCostReductionEffect extends CostModificationEffectImpl {
InfectiousCurseCostReductionEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.staticText = "Spells you cast that target enchanted player cost {1} less to cast";
}
private InfectiousCurseCostReductionEffect(InfectiousCurseCostReductionEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
CardUtil.reduceCost(abilityToModify, 1);
return true;
}
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (!(abilityToModify instanceof SpellAbility)) {
return false;
}
if (!source.isControlledBy(abilityToModify.getControllerId())) {
return false;
}
Permanent enchantment = game.getPermanent(source.getSourceId());
if (enchantment == null || enchantment.getAttachedTo() == null) {
return false;
}
Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId());
Set<UUID> allTargets;
if (spell != null) {
// real cast
allTargets = CardUtil.getAllSelectedTargets(abilityToModify, game);
} else {
// playable
allTargets = CardUtil.getAllPossibleTargets(abilityToModify, game);
}
// try to reduce all the time (if it possible to target)
return allTargets.stream().anyMatch(target -> Objects.equals(target, enchantment.getAttachedTo()));
}
@Override
public InfectiousCurseCostReductionEffect copy() {
return new InfectiousCurseCostReductionEffect(this);
}
}

View file

@ -1,16 +1,23 @@
package mage.cards.a;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.CardsInHandCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.abilities.keyword.TransformAbility;
import mage.abilities.mana.BlackManaAbility;
import mage.cards.*;
import mage.constants.*;
import mage.filter.StaticFilters;
@ -28,33 +35,43 @@ import java.util.UUID;
/**
* @author Susucr
*/
public final class AclazotzDeepestBetrayal extends CardImpl {
public final class AclazotzDeepestBetrayal extends TransformingDoubleFacedCard {
private static final Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 2, TargetController.ANY);
private static final Hint hint = new ConditionHint(condition);
public AclazotzDeepestBetrayal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.secondSideCardClazz = mage.cards.t.TempleOfTheDead.class;
super(ownerId, setInfo,
new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.BAT, SubType.GOD}, "{3}{B}{B}",
"Temple of the Dead",
new SuperType[]{}, new CardType[]{CardType.LAND}, new SubType[]{}, "");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.BAT);
this.subtype.add(SubType.GOD);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
this.getLeftHalfCard().setPT(4, 4);
// Flying
this.addAbility(FlyingAbility.getInstance());
this.getLeftHalfCard().addAbility(FlyingAbility.getInstance());
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
this.getLeftHalfCard().addAbility(LifelinkAbility.getInstance());
// Whenever Aclazotz attacks, each opponent discards a card. For each opponent who can't, you draw a card.
this.addAbility(new AttacksTriggeredAbility(new AclazotzDeepestBetrayalEffect()));
this.getLeftHalfCard().addAbility(new AttacksTriggeredAbility(new AclazotzDeepestBetrayalEffect()));
// Whenever an opponent discards a land card, create a 1/1 black Bat creature token with flying.
this.addAbility(new AclazotzDeepestBetrayalTriggeredAbility());
this.getLeftHalfCard().addAbility(new AclazotzDeepestBetrayalTriggeredAbility());
// When Aclazotz dies, return it to the battlefield tapped and transformed under its owner's control.
this.addAbility(new TransformAbility());
this.addAbility(new DiesSourceTriggeredAbility(new AclazotzDeepestBetrayalTransformEffect()));
this.getLeftHalfCard().addAbility(new DiesSourceTriggeredAbility(new AclazotzDeepestBetrayalTransformEffect()));
// Temple of the Dead
// {T}: Add {B}.
this.getRightHalfCard().addAbility(new BlackManaAbility());
// {2}{B}, {T}: Transform Temple of the Dead. Activate only if a player has one or fewer cards in hand and only as a sorcery.
Ability ability = new ActivateIfConditionActivatedAbility(
new TransformSourceEffect(), new ManaCostsImpl<>("{2}{B}"), condition
).setTiming(TimingRule.SORCERY);
ability.addCost(new TapSourceCost());
this.getRightHalfCard().addAbility(ability.addHint(hint));
}
private AclazotzDeepestBetrayal(final AclazotzDeepestBetrayal card) {

View file

@ -1,4 +1,3 @@
package mage.cards.a;
import java.util.UUID;
@ -28,7 +27,9 @@ public final class AcolyteOfTheInferno extends CardImpl {
this.addAbility(new RenownAbility(1));
// Whenever Acolyte of the Inferno becomes blocked by a creature, it deals 2 damage to that creature
this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(new DamageTargetEffect(2, true, "that creature", "it"), false));
this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(
new DamageTargetEffect(2, "it")
.withTargetDescription("that creature"), false));
}
private AcolyteOfTheInferno(final AcolyteOfTheInferno card) {

View file

@ -2,16 +2,14 @@ package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.DevotionCount;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.events.PreventDamageEvent;
import mage.game.events.PreventedDamageEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
@ -46,16 +44,14 @@ public final class AcolytesReward extends CardImpl {
class AcolytesRewardEffect extends PreventionEffectImpl {
protected int amount = 0;
AcolytesRewardEffect() {
super(Duration.EndOfTurn);
super(Duration.EndOfTurn, 0, false, true, DevotionCount.W);
staticText = "Prevent the next X damage that would be dealt to target creature this turn, where X is your devotion to white. If damage is prevented this way, {this} deals that much damage to any target";
}
private AcolytesRewardEffect(final AcolytesRewardEffect effect) {
super(effect);
this.amount = effect.amount;
}
@Override
@ -63,64 +59,25 @@ class AcolytesRewardEffect extends PreventionEffectImpl {
return new AcolytesRewardEffect(this);
}
@Override
public void init(Ability source, Game game) {
super.init(source, game);
amount = DevotionCount.W.calculate(game, source, this);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
boolean result = false;
int toPrevent = amount;
if (event.getAmount() < this.amount) {
toPrevent = event.getAmount();
amount -= event.getAmount();
} else {
amount = 0;
PreventionEffectData preventionData = preventDamageAction(event, source, game);
if (preventionData.getPreventedDamage() > 0) {
Permanent targetCreature = game.getPermanent(source.getFirstTarget());
if (targetCreature != null) {
targetCreature.damage(preventionData.getPreventedDamage(), source.getSourceId(), source, game, false, true);
}
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (targetCreature != null) {
targetPlayer.damage(preventionData.getPreventedDamage(), source.getSourceId(), source, game, false, true);
}
}
GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), toPrevent, ((DamageEvent) event).isCombatDamage());
if (game.replaceEvent(preventEvent)) {
return result;
}
Permanent targetCreature = game.getPermanent(event.getTargetId());
if (targetCreature == null) {
return result;
}
if (amount == 0) {
this.used = true;
this.discard();
}
if (event.getAmount() >= toPrevent) {
event.setAmount(event.getAmount() - toPrevent);
} else {
event.setAmount(0);
result = true;
}
if (toPrevent == 0) {
return result;
}
game.informPlayers("Acolyte's Reward prevented " + toPrevent + " to " + targetCreature.getName());
game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), toPrevent));
Player targetPlayer = game.getPlayer(source.getTargets().get(1).getFirstTarget());
if (targetPlayer != null) {
targetPlayer.damage(toPrevent, source.getSourceId(), source, game);
game.informPlayers("Acolyte's Reward deals " + toPrevent + " damage to " + targetPlayer.getLogName());
return result;
}
Permanent targetDamageCreature = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (targetDamageCreature == null) {
return result;
}
targetDamageCreature.damage(toPrevent, source.getSourceId(), source, game, false, true);
game.informPlayers("Acolyte's Reward deals " + toPrevent + " damage to " + targetDamageCreature.getName());
return result;
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return !this.used && super.applies(event, source, game) && event.getTargetId().equals(source.getFirstTarget());
return super.applies(event, source, game) && event.getTargetId().equals(source.getFirstTarget());
}
}

View file

@ -41,7 +41,7 @@ public final class AdrenalineJockey extends CardImpl {
// Whenever a player casts a spell, if it's not their turn, this creature deals 4 damage to them.
this.addAbility(new SpellCastAllTriggeredAbility(
new DamageTargetEffect(4, true, "them"),
new DamageTargetEffect(4).withTargetDescription("them"),
filter, false, SetTargetPointer.PLAYER
));

View file

@ -1,17 +1,28 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate;
import mage.game.Game;
import mage.game.permanent.token.HeroToken;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author TheElk801
@ -28,8 +39,7 @@ public final class AerithRescueMission extends CardImpl {
// * Take 59 Flights of Stairs -- Tap up to three target creatures. Put a stun counter on one of them.
this.getSpellAbility().addMode(new Mode(new TapTargetEffect())
.addEffect(new AddCountersTargetEffect(CounterType.STUN.createInstance())
.setText("Put a stun counter on one of them"))
.addEffect(new AerithRescueMissionStunEffect())
.addTarget(new TargetCreaturePermanent(0, 3))
.withFlavorWord("Take 59 Flights of Stairs"));
}
@ -43,3 +53,34 @@ public final class AerithRescueMission extends CardImpl {
return new AerithRescueMission(this);
}
}
class AerithRescueMissionStunEffect extends OneShotEffect {
AerithRescueMissionStunEffect() {
super(Outcome.Detriment);
staticText = "Put a stun counter on one of them";
}
private AerithRescueMissionStunEffect(final AerithRescueMissionStunEffect effect) {
super(effect);
}
@Override
public AerithRescueMissionStunEffect copy() {
return new AerithRescueMissionStunEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
FilterPermanent filter = new FilterPermanent("creature to put a stun counter on");
filter.add(new PermanentReferenceInCollectionPredicate(this.getTargetPointer().getTargets(game, source).stream()
.map(game::getPermanent).collect(Collectors.toList()), game));
Target target = new TargetPermanent(filter).withNotTarget(true);
if (target.choose(Outcome.UnboostCreature, source.getControllerId(), source, game)) {
Effect eff = new AddCountersTargetEffect(CounterType.STUN.createInstance());
eff.setTargetPointer(new FixedTarget(target.getFirstTarget(), game));
return eff.apply(game, source);
}
return false;
}
}

View file

@ -1,13 +1,13 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.common.DealsCombatDamageToAPlayerOrBattleTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.CardType;
import mage.constants.SubType;
@ -16,23 +16,28 @@ import java.util.UUID;
/**
* @author TheElk801
*/
public final class AetherbladeAgent extends CardImpl {
public final class AetherbladeAgent extends TransformingDoubleFacedCard {
public AetherbladeAgent(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ROGUE);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
this.secondSideCardClazz = mage.cards.g.GitaxianMindstinger.class;
super(ownerId, setInfo,
new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.ROGUE}, "{1}{B}",
"Gitaxian Mindstinger",
new CardType[]{CardType.CREATURE}, new SubType[]{SubType.PHYREXIAN, SubType.ROGUE}, "UB");
this.getLeftHalfCard().setPT(1, 1);
this.getRightHalfCard().setPT(3, 3);
// Deathtouch
this.addAbility(DeathtouchAbility.getInstance());
this.getLeftHalfCard().addAbility(DeathtouchAbility.getInstance());
// {4}{U/P}: Transform Aetherblade Agent. Activate only as a sorcery.
this.addAbility(new TransformAbility());
this.addAbility(new ActivateAsSorceryActivatedAbility(new TransformSourceEffect(), new ManaCostsImpl<>("{4}{U/P}")));
this.getLeftHalfCard().addAbility(new ActivateAsSorceryActivatedAbility(new TransformSourceEffect(), new ManaCostsImpl<>("{4}{U/P}")));
// Gitaxian Mindstinger
// Deathtouch
this.getRightHalfCard().addAbility(DeathtouchAbility.getInstance());
// Whenever Gitaxian Mindstinger deals combat damage to a player or battle, draw a card.
this.getRightHalfCard().addAbility(new DealsCombatDamageToAPlayerOrBattleTriggeredAbility(new DrawCardSourceControllerEffect(1),false));
}
private AetherbladeAgent(final AetherbladeAgent card) {

View file

@ -1,33 +1,49 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.TransformIntoSourceTriggeredAbility;
import mage.abilities.common.WerewolfBackTriggeredAbility;
import mage.abilities.common.WerewolfFrontTriggeredAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetArtifactPermanent;
import java.util.Optional;
import java.util.UUID;
/**
* @author BetaSteward
*/
public final class AfflictedDeserter extends CardImpl {
public final class AfflictedDeserter extends TransformingDoubleFacedCard {
public AfflictedDeserter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WEREWOLF);
this.secondSideCardClazz = mage.cards.w.WerewolfRansacker.class;
this.power = new MageInt(3);
this.toughness = new MageInt(2);
super(ownerId, setInfo,
new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.WEREWOLF}, "{3}{R}",
"Werewolf Ransacker",
new CardType[]{CardType.CREATURE}, new SubType[]{SubType.WEREWOLF}, "R");
this.getLeftHalfCard().setPT(3, 2);
this.getRightHalfCard().setPT(5, 4);
// At the beginning of each upkeep, if no spells were cast last turn, transform Afflicted Deserter.
this.addAbility(new TransformAbility());
this.addAbility(new WerewolfFrontTriggeredAbility());
this.getLeftHalfCard().addAbility(new WerewolfFrontTriggeredAbility());
// Werewolf Ransacker
// Whenever this creature transforms into Werewolf Ransacker, you may destroy target artifact. If that artifact is put into a graveyard this way, Werewolf Ransacker deals 3 damage to that artifact's controller.
Ability ability = new TransformIntoSourceTriggeredAbility(new WerewolfRansackerEffect(), true, true);
ability.addTarget(new TargetArtifactPermanent());
this.getRightHalfCard().addAbility(ability);
// At the beginning of each upkeep, if a player cast two or more spells last turn, transform Werewolf Ransacker.
this.getRightHalfCard().addAbility(new WerewolfBackTriggeredAbility());
}
private AfflictedDeserter(final AfflictedDeserter card) {
@ -39,3 +55,39 @@ public final class AfflictedDeserter extends CardImpl {
return new AfflictedDeserter(this);
}
}
class WerewolfRansackerEffect extends OneShotEffect {
WerewolfRansackerEffect() {
super(Outcome.DestroyPermanent);
staticText = "destroy target artifact. If that artifact is put into a graveyard this way, " +
"{this} deals 3 damage to that artifact's controller";
}
private WerewolfRansackerEffect(final WerewolfRansackerEffect effect) {
super(effect);
}
@Override
public WerewolfRansackerEffect copy() {
return new WerewolfRansackerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent == null) {
return false;
}
permanent.destroy(source, game);
if (game.getState().getZone(permanent.getId()) != Zone.GRAVEYARD) {
return true;
}
Optional.of(permanent)
.map(Controllable::getControllerId)
.map(game::getPlayer)
.ifPresent(player -> player.damage(3, source, game));
return true;
}
}

View file

@ -0,0 +1,66 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.MenaceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AgentVenom extends CardImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another nontoken creature you control");
static {
filter.add(AnotherPredicate.instance);
filter.add(TokenPredicate.FALSE);
}
public AgentVenom(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.SYMBIOTE);
this.subtype.add(SubType.SOLDIER);
this.subtype.add(SubType.HERO);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Flash
this.addAbility(FlashAbility.getInstance());
// Menace
this.addAbility(new MenaceAbility(false));
// Whenever another nontoken creature you control dies, you draw a card and lose 1 life.
Ability ability = new DiesCreatureTriggeredAbility(
new DrawCardSourceControllerEffect(1, true), false, filter
);
ability.addEffect(new LoseLifeSourceControllerEffect(1).setText("and lose 1 life"));
this.addAbility(ability);
}
private AgentVenom(final AgentVenom card) {
super(card);
}
@Override
public AgentVenom copy() {
return new AgentVenom(this);
}
}

View file

@ -0,0 +1,48 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTappedUnlessAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.common.YouControlABasicLandCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.abilities.mana.BlueManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AgnaQela extends CardImpl {
public AgnaQela(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// This land enters tapped unless you control a basic land.
this.addAbility(new EntersBattlefieldTappedUnlessAbility(YouControlABasicLandCondition.instance)
.addHint(YouControlABasicLandCondition.getHint()));
// {T}: Add {U}.
this.addAbility(new BlueManaAbility());
// {2}{U}, {T}: Draw a card, then discard a card.
Ability ability = new SimpleActivatedAbility(
new DrawDiscardControllerEffect(1, 1), new ManaCostsImpl<>("{2}{U}")
);
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
private AgnaQela(final AgnaQela card) {
super(card);
}
@Override
public AgnaQela copy() {
return new AgnaQela(this);
}
}

View file

@ -0,0 +1,41 @@
package mage.cards.a;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.StaticFilters;
import mage.game.permanent.token.ClueArtifactToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AirNomadLegacy extends CardImpl {
public AirNomadLegacy(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{U}");
// When this enchantment enters, create a Clue token.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ClueArtifactToken())));
// Creatures you control with flying get +1/+1.
this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(
1, 1, Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURE_FLYING
).setText("creatures you control with flying get +1/+1")));
}
private AirNomadLegacy(final AirNomadLegacy card) {
super(card);
}
@Override
public AirNomadLegacy copy() {
return new AirNomadLegacy(this);
}
}

View file

@ -0,0 +1,51 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.condition.Condition;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.AttackedThisTurnSourceCondition;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AirNomadStudent extends CardImpl {
private static final Condition condition = new InvertCondition(
AttackedThisTurnSourceCondition.instance, "{this} didn't attack this turn"
);
public AirNomadStudent(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.MONK);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// At the beginning of your end step, if this creature didn't attack this turn, put a +1/+1 counter on it.
this.addAbility(new BeginningOfEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())
.setText("put a +1/+1 counter on it")).withInterveningIf(condition));
}
private AirNomadStudent(final AirNomadStudent card) {
super(card);
}
@Override
public AirNomadStudent copy() {
return new AirNomadStudent(this);
}
}

View file

@ -0,0 +1,59 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.effects.common.ExileThenReturnTargetEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.keyword.AirbendTargetEffect;
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AirbenderAscension extends CardImpl {
private static final Condition condition = new SourceHasCounterCondition(CounterType.QUEST, 4);
public AirbenderAscension(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// When this enchantment enters, airbend up to one target creature.
Ability ability = new EntersBattlefieldTriggeredAbility(new AirbendTargetEffect());
ability.addTarget(new TargetCreaturePermanent(0, 1));
this.addAbility(ability);
// Whenever a creature you control enters, put a quest counter on this enchantment.
this.addAbility(new EntersBattlefieldAllTriggeredAbility(
new AddCountersSourceEffect(CounterType.QUEST.createInstance()),
StaticFilters.FILTER_CONTROLLED_CREATURE
));
// At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control.
ability = new BeginningOfEndStepTriggeredAbility(
new ExileThenReturnTargetEffect(false, false)
).withInterveningIf(condition);
ability.addTarget(new TargetControlledCreaturePermanent(0, 1));
this.addAbility(ability);
}
private AirbenderAscension(final AirbenderAscension card) {
super(card);
}
@Override
public AirbenderAscension copy() {
return new AirbenderAscension(this);
}
}

View file

@ -0,0 +1,43 @@
package mage.cards.a;
import mage.abilities.Mode;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.keyword.AirbendTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetAttackingCreature;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AirbendersReversal extends CardImpl {
public AirbendersReversal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
this.subtype.add(SubType.LESSON);
// Choose one --
// * Destroy target attacking creature.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetAttackingCreature());
// * Airbend target creature you control.
this.getSpellAbility().addMode(new Mode(new AirbendTargetEffect())
.addTarget(new TargetControlledCreaturePermanent()));
}
private AirbendersReversal(final AirbendersReversal card) {
super(card);
}
@Override
public AirbendersReversal copy() {
return new AirbendersReversal(this);
}
}

View file

@ -0,0 +1,39 @@
package mage.cards.a;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.keyword.AirbendTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetNonlandPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AirbendingLesson extends CardImpl {
public AirbendingLesson(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
this.subtype.add(SubType.LESSON);
// Airbend target nonland permanent.
this.getSpellAbility().addEffect(new AirbendTargetEffect());
this.getSpellAbility().addTarget(new TargetNonlandPermanent());
// Draw a card.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("<br>"));
}
private AirbendingLesson(final AirbendingLesson card) {
super(card);
}
@Override
public AirbendingLesson copy() {
return new AirbendingLesson(this);
}
}

View file

@ -0,0 +1,48 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.mana.BlueManaAbility;
import mage.abilities.mana.RedManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AirshipEngineRoom extends CardImpl {
public AirshipEngineRoom(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// This land enters tapped.
this.addAbility(new EntersBattlefieldTappedAbility());
// {T}: Add {U} or {R}.
this.addAbility(new BlueManaAbility());
this.addAbility(new RedManaAbility());
// {4}, {T}, Sacrifice this land: Draw a card.
Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
}
private AirshipEngineRoom(final AirshipEngineRoom card) {
super(card);
}
@Override
public AirshipEngineRoom copy() {
return new AirshipEngineRoom(this);
}
}

View file

@ -1,190 +0,0 @@
package mage.cards.a;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.dynamicvalue.common.CreaturesYouControlCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.CatWarrior21Token;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetAnyTarget;
import mage.util.CardUtil;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Susucr
*/
public final class AjaniNacatlAvenger extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.CAT, "Cat you control");
public AjaniNacatlAvenger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.AJANI);
this.setStartingLoyalty(3);
this.color.setRed(true);
this.color.setWhite(true);
this.nightCard = true;
// +2: Put a +1/+1 counter on each Cat you control.
this.addAbility(new LoyaltyAbility(
new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter), 2
));
// 0: Create a 2/1 white Car Warrior creature token. When you do, if you control a red permanent other than Ajani, Nacatl Avenger, he deals damage equal to the number of creatures you control to any target.
this.addAbility(new LoyaltyAbility(new AjaniNacatlAvengerZeroEffect(), 0));
// -4: Each opponent chooses an artifact, a creature, an enchantment and a planeswalker from among the nonland permanents they control, then sacrifices the rest.
this.addAbility(new LoyaltyAbility(new AjaniNacatlAvengerMinusFourEffect(), -4));
}
private AjaniNacatlAvenger(final AjaniNacatlAvenger card) {
super(card);
}
@Override
public AjaniNacatlAvenger copy() {
return new AjaniNacatlAvenger(this);
}
}
class AjaniNacatlAvengerZeroEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent("red permanent other than {this}");
static {
filter.add(new ColorPredicate(ObjectColor.RED));
filter.add(AnotherPredicate.instance);
}
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, true);
AjaniNacatlAvengerZeroEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "Create a 2/1 white Cat Warrior creature token. "
+ "When you do, if you control a red permanent other than {this}, "
+ "he deals damage equal to the number of creatures you control to any target.";
}
private AjaniNacatlAvengerZeroEffect(final AjaniNacatlAvengerZeroEffect effect) {
super(effect);
}
@Override
public AjaniNacatlAvengerZeroEffect copy() {
return new AjaniNacatlAvengerZeroEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (!new CreateTokenEffect(new CatWarrior21Token()).apply(game, source)) {
return false;
}
ReflexiveTriggeredAbility reflexive = new ReflexiveTriggeredAbility(
new DamageTargetEffect(CreaturesYouControlCount.PLURAL),
false,
"When you do, if you control a red permanent other than {this}, "
+ "he deals damage equal to the number of creatures you control to any target.",
condition
);
reflexive.addTarget(new TargetAnyTarget());
game.fireReflexiveTriggeredAbility(reflexive, source);
return true;
}
}
// Inspired by Mythos of Snapdax
class AjaniNacatlAvengerMinusFourEffect extends OneShotEffect {
private static final List<CardType> cardTypes = Arrays.asList(
CardType.ARTIFACT,
CardType.CREATURE,
CardType.ENCHANTMENT,
CardType.PLANESWALKER
);
AjaniNacatlAvengerMinusFourEffect() {
super(Outcome.Benefit);
staticText = "Each opponent chooses an artifact, a creature, an enchantment and a planeswalker "
+ "from among the nonland permanents they control, then sacrifices the rest.";
}
private AjaniNacatlAvengerMinusFourEffect(final AjaniNacatlAvengerMinusFourEffect effect) {
super(effect);
}
@Override
public AjaniNacatlAvengerMinusFourEffect copy() {
return new AjaniNacatlAvengerMinusFourEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
List<Player> playerList = game
.getOpponents(controller.getId())
.stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.collect(Collectors.toList());
Set<UUID> toKeep = new HashSet<>();
for (Player player : playerList) {
for (CardType cardType : cardTypes) {
String message = CardUtil.addArticle(cardType.toString());
FilterPermanent filter = new FilterNonlandPermanent(message);
filter.add(cardType.getPredicate());
filter.add(new ControllerIdPredicate(player.getId()));
if (game.getBattlefield().count(filter, source.getControllerId(), source, game) == 0) {
continue;
}
TargetPermanent target = new TargetPermanent(filter);
target.withNotTarget(true);
player.choose(outcome, target, source, game);
toKeep.add(target.getFirstTarget());
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_NON_LAND, source.getControllerId(), game)) {
if (permanent == null || toKeep.contains(permanent.getId()) || !controller.hasOpponent(permanent.getControllerId(), game)) {
continue;
}
permanent.sacrifice(source, game);
}
return true;
}
}

View file

@ -1,27 +1,49 @@
package mage.cards.a;
import mage.MageInt;
import mage.constants.Pronoun;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.DiesOneOrMoreTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.dynamicvalue.common.CreaturesYouControlCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.ExileAndReturnSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.cards.CardSetInfo;
import mage.cards.TransformingDoubleFacedCard;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.CatWarrior21Token;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetAnyTarget;
import mage.util.CardUtil;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Susucr
*/
public final class AjaniNacatlPariah extends CardImpl {
public final class AjaniNacatlPariah extends TransformingDoubleFacedCard {
public static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.CAT, "other Cats you control");
private static final FilterControlledCreaturePermanent nacatlAvengerFilter = new FilterControlledCreaturePermanent(SubType.CAT, "Cat you control");
static {
filter.add(AnotherPredicate.instance);
@ -29,25 +51,34 @@ public final class AjaniNacatlPariah extends CardImpl {
}
public AjaniNacatlPariah(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
super(ownerId, setInfo,
new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.CAT, SubType.WARRIOR}, "{1}{W}",
"Ajani, Nacatl Avenger",
new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.PLANESWALKER}, new SubType[]{SubType.AJANI}, "RW");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.CAT);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(1);
this.toughness = new MageInt(2);
this.secondSideCardClazz = mage.cards.a.AjaniNacatlAvenger.class;
this.getLeftHalfCard().setPT(1, 2);
this.getRightHalfCard().setStartingLoyalty(3);
// When Ajani, Nacatl Pariah enters the battlefield, create a 2/1 white Cat Warrior creature token.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new CatWarrior21Token())));
this.getLeftHalfCard().addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new CatWarrior21Token())));
// Whenever one or more other Cats you control die, you may exile Ajani, then return him to the battlefield transformed under his owner's control.
this.addAbility(new TransformAbility());
this.addAbility(new DiesOneOrMoreTriggeredAbility(
this.getLeftHalfCard().addAbility(new DiesOneOrMoreTriggeredAbility(
new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.HE),
filter,
true));
// Ajani, Nacatl Avenger
// +2: Put a +1/+1 counter on each Cat you control.
this.getRightHalfCard().addAbility(new LoyaltyAbility(
new AddCountersAllEffect(CounterType.P1P1.createInstance(), nacatlAvengerFilter), 2
));
// 0: Create a 2/1 white Car Warrior creature token. When you do, if you control a red permanent other than Ajani, Nacatl Avenger, he deals damage equal to the number of creatures you control to any target.
this.getRightHalfCard().addAbility(new LoyaltyAbility(new AjaniNacatlAvengerZeroEffect(), 0));
// -4: Each opponent chooses an artifact, a creature, an enchantment and a planeswalker from among the nonland permanents they control, then sacrifices the rest.
this.getRightHalfCard().addAbility(new LoyaltyAbility(new AjaniNacatlAvengerMinusFourEffect(), -4));
}
private AjaniNacatlPariah(final AjaniNacatlPariah card) {
@ -59,3 +90,116 @@ public final class AjaniNacatlPariah extends CardImpl {
return new AjaniNacatlPariah(this);
}
}
class AjaniNacatlAvengerZeroEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent("red permanent other than {this}");
static {
filter.add(new ColorPredicate(ObjectColor.RED));
filter.add(AnotherPredicate.instance);
}
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, true);
AjaniNacatlAvengerZeroEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "Create a 2/1 white Cat Warrior creature token. "
+ "When you do, if you control a red permanent other than {this}, "
+ "he deals damage equal to the number of creatures you control to any target.";
}
private AjaniNacatlAvengerZeroEffect(final AjaniNacatlAvengerZeroEffect effect) {
super(effect);
}
@Override
public AjaniNacatlAvengerZeroEffect copy() {
return new AjaniNacatlAvengerZeroEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (!new CreateTokenEffect(new CatWarrior21Token()).apply(game, source)) {
return false;
}
ReflexiveTriggeredAbility reflexive = new ReflexiveTriggeredAbility(
new DamageTargetEffect(CreaturesYouControlCount.PLURAL),
false,
"When you do, if you control a red permanent other than {this}, "
+ "he deals damage equal to the number of creatures you control to any target.",
condition
);
reflexive.addTarget(new TargetAnyTarget());
game.fireReflexiveTriggeredAbility(reflexive, source);
return true;
}
}
// Inspired by Mythos of Snapdax
class AjaniNacatlAvengerMinusFourEffect extends OneShotEffect {
private static final List<CardType> cardTypes = Arrays.asList(
CardType.ARTIFACT,
CardType.CREATURE,
CardType.ENCHANTMENT,
CardType.PLANESWALKER
);
AjaniNacatlAvengerMinusFourEffect() {
super(Outcome.Benefit);
staticText = "Each opponent chooses an artifact, a creature, an enchantment and a planeswalker "
+ "from among the nonland permanents they control, then sacrifices the rest.";
}
private AjaniNacatlAvengerMinusFourEffect(final AjaniNacatlAvengerMinusFourEffect effect) {
super(effect);
}
@Override
public AjaniNacatlAvengerMinusFourEffect copy() {
return new AjaniNacatlAvengerMinusFourEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
List<Player> playerList = game
.getOpponents(controller.getId())
.stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.collect(Collectors.toList());
Set<UUID> toKeep = new HashSet<>();
for (Player player : playerList) {
for (CardType cardType : cardTypes) {
String message = CardUtil.addArticle(cardType.toString());
FilterPermanent filter = new FilterNonlandPermanent(message);
filter.add(cardType.getPredicate());
filter.add(new ControllerIdPredicate(player.getId()));
if (game.getBattlefield().count(filter, source.getControllerId(), source, game) == 0) {
continue;
}
TargetPermanent target = new TargetPermanent(filter);
target.withNotTarget(true);
player.choose(outcome, target, source, game);
toKeep.add(target.getFirstTarget());
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_NON_LAND, source.getControllerId(), game)) {
if (permanent == null || toKeep.contains(permanent.getId()) || !controller.hasOpponent(permanent.getControllerId(), game)) {
continue;
}
permanent.sacrifice(source, game);
}
return true;
}
}

View file

@ -27,9 +27,9 @@ public final class AlabornZealot extends CardImpl {
// When Alaborn Zealot blocks a creature, destroy that creature and Alaborn Zealot.
TriggeredAbility ability = new BlocksCreatureTriggeredAbility(
new DestroyTargetEffect().setText("destroy that creature")
new DestroyTargetEffect().setText("destroy both")
);
ability.addEffect(new DestroySourceEffect().setText("and {this}"));
ability.addEffect(new DestroySourceEffect().setText(" creatures"));
ability.setTriggerPhrase("When {this} blocks a creature, ");
this.addAbility(ability);
}

Some files were not shown because too many files have changed in this diff Show more