· 4 years ago · May 22, 2021, 10:00 PM
1-- Lua code for parsing json: https://github.com/BanMing/BanMingLuaLab/blob/master/LuaTest/Test/LuaJson.lua
2luaJson = {}
3local function json2true(str, from, to)
4 return true, from + 3
5end
6
7local function json2false(str, from, to)
8 return false, from + 4
9end
10
11local function json2null(str, from, to)
12 return nil, from + 3
13end
14
15local function json2nan(str, from, to)
16 return nul, from + 2
17end
18
19local numberchars = {
20 ['-'] = true,
21 ['+'] = true,
22 ['.'] = true,
23 ['0'] = true,
24 ['1'] = true,
25 ['2'] = true,
26 ['3'] = true,
27 ['4'] = true,
28 ['5'] = true,
29 ['6'] = true,
30 ['7'] = true,
31 ['8'] = true,
32 ['9'] = true,
33}
34
35local function json2number(str, from, to)
36 local i = from + 1
37 while (i <= to) do
38 local char = string.sub(str, i, i)
39 if not numberchars[char] then
40 break
41 end
42 i = i + 1
43 end
44 local num = tonumber(string.sub(str, from, i - 1))
45 if not num then
46 Log("red", 'json格式错误,不正确的数字, 错误位置:', from)
47 end
48 return num, i - 1
49end
50
51local function json2string(str, from, to)
52 local ignor = false
53 for i = from + 1, to do
54 local char = string.sub(str, i, i)
55 if not ignor then
56 if char == '\"' then
57 return string.sub(str, from + 1, i - 1), i
58 elseif char == '\\' then
59 ignor = true
60 end
61 else
62 ignor = false
63 end
64 end
65 Log("red", 'json格式错误,字符串没有找到结尾, 错误位置:{from}', from)
66end
67
68local function json2array(str, from, to)
69 local result = {}
70 from = from or 1
71 local pos = from + 1
72 local to = to or string.len(str)
73 while (pos <= to) do
74 local char = string.sub(str, pos, pos)
75 if char == '\"' then
76 result[#result + 1], pos = json2string(str, pos, to)
77 --[[ elseif char == ' ' then
78
79 elseif char == ':' then
80
81 elseif char == ',' then]]
82 elseif char == '[' then
83 result[#result + 1], pos = json2array(str, pos, to)
84 elseif char == '{' then
85 result[#result + 1], pos = luaJson.json2table(str, pos, to)
86 elseif char == ']' then
87 return result, pos
88 elseif (char == 'f' or char == 'F') then
89 result[#result + 1], pos = json2false(str, pos, to)
90 elseif (char == 't' or char == 'T') then
91 result[#result + 1], pos = json2true(str, pos, to)
92 elseif (char == 'n') then
93 result[#result + 1], pos = json2null(str, pos, to)
94 elseif (char == 'N') then
95 result[#result + 1], pos = json2nan(str, pos, to)
96 elseif numberchars[char] then
97 result[#result + 1], pos = json2number(str, pos, to)
98 end
99 pos = pos + 1
100 end
101 Log("red", 'json格式错误,表没有找到结尾, 错误位置:{from}', from)
102end
103
104local function string2json(key, value)
105 return string.format("\"%s\":\"%s\",", key, value)
106end
107
108local function number2json(key, value)
109 return string.format("\"%s\":%s,", key, value)
110end
111
112local function boolean2json(key, value)
113 value = value == nil and false or value
114 return string.format("\"%s\":%s,", key, tostring(value))
115end
116
117local function array2json(key, value)
118 local str = "["
119 for k, v in pairs(value) do
120 str = str .. luaJson.table2json(v) .. ","
121 end
122 str = string.sub(str, 1, string.len(str) - 1) .. "]"
123 return string.format("\"%s\":%s,", key, str)
124end
125
126local function isArrayTable(t)
127
128 if type(t) ~= "table" then
129 return false
130 end
131
132 local n = #t
133 for i, v in pairs(t) do
134 if type(i) ~= "number" then
135 return false
136 end
137
138 if i > n then
139 return false
140 end
141 end
142
143 return true
144end
145
146local function table2json(key, value)
147 if isArrayTable(value) then
148 return array2json(key, value)
149 end
150 local tableStr = luaJson.table2json(value)
151 return string.format("\"%s\":%s,", key, tableStr)
152end
153
154
155
156function luaJson.json2table(str, from, to)
157 local result = {}
158 from = from or 1
159 local pos = from + 1
160 local to = to or string.len(str)
161 local key
162 while (pos <= to) do
163 local char = string.sub(str, pos, pos)
164 --Log("yellow", pos, "-->", char)
165 if char == '\"' then
166 if not key then
167 key, pos = json2string(str, pos, to)
168 else
169 result[key], pos = json2string(str, pos, to)
170 key = nil
171 end
172 --[[ elseif char == ' ' then
173
174 elseif char == ':' then
175
176 elseif char == ',' then]]
177 elseif char == '[' then
178 if not key then
179 key, pos = json2array(str, pos, to)
180 else
181 result[key], pos = json2array(str, pos, to)
182 key = nil
183 end
184 elseif char == '{' then
185 if not key then
186 key, pos = luaJson.json2table(str, pos, to)
187 else
188 result[key], pos = luaJson.json2table(str, pos, to)
189 key = nil
190 end
191 elseif char == '}' then
192 return result, pos
193 elseif (char == 'f' or char == 'F') then
194 result[key], pos = json2false(str, pos, to)
195 key = nil
196 elseif (char == 't' or char == 'T') then
197 result[key], pos = json2true(str, pos, to)
198 key = nil
199 elseif (char == 'n') then
200 result[key], pos = json2null(str, pos, to)
201 key = nil
202 elseif (char == 'N') then
203 result[key], pos = json2nan(str, pos, to)
204 key = nil
205 elseif numberchars[char] then
206 if not key then
207 key, pos = json2number(str, pos, to)
208 else
209 result[key], pos = json2number(str, pos, to)
210 key = nil
211 end
212 end
213 pos = pos + 1
214 end
215 Log("red", 'json格式错误,表没有找到结尾, 错误位置:{from}', from)
216end
217
218--json格式中表示字符串不能使用单引号
219local jsonfuncs = {
220 ['\"'] = json2string,
221 ['['] = json2array,
222 ['{'] = luaJson.json2table,
223 ['f'] = json2false,
224 ['F'] = json2false,
225 ['t'] = json2true,
226 ['T'] = json2true,
227}
228
229function luaJson.json2lua(str)
230 local char = string.sub(str, 1, 1)
231 local func = jsonfuncs[char]
232 if func then
233 return func(str, 1, string.len(str))
234 end
235 if numberchars[char] then
236 return json2number(str, 1, string.len(str))
237 end
238end
239
240function luaJson.table2json(tab)
241 local str = "{"
242 for k, v in pairs(tab) do
243 if type(v) == "string" then
244 str = str .. string2json(k, v)
245 elseif type(v) == "number" then
246 str = str .. number2json(k, v)
247 elseif type(v) == "boolean" then
248 str = str .. boolean2json(k, v)
249 elseif type(v) == "table" then
250 str = str .. table2json(k, v)
251 end
252 end
253 str = string.sub(str, 1, string.len(str) - 1)
254 return str .. "}"
255end
256
257-- Expansions
258
259expansions="\[{\"name\":\"Double Masters\",\"code\":\"2xm\"},{\"name\":\"Jumpstart\",\"code\":\"jmp\"},{\"name\":\"Core Set 2021\",\"code\":\"m21\"},{\"name\":\"Signature Spellbook: Chandra\",\"code\":\"ss3\"},{\"name\":\"Jumpstart Front Cards\",\"code\":\"fjmp\"},{\"name\":\"Jumpstart Tokens\",\"code\":\"tjmp\"},{\"name\":\"Core Set 2021 Tokens\",\"code\":\"tm21\"},{\"name\":\"Secret Lair: Ultimate Edition\",\"code\":\"slu\"},{\"name\":\"Historic Anthology 3\",\"code\":\"ha3\"},{\"name\":\"Love Your LGS\",\"code\":\"plgs\"},{\"name\":\"Signature Spellbook: Chandra\",\"code\":\"ss3\"},{\"name\":\"Secret Lair: Ultimate Edition\",\"code\":\"slu\"},{\"name\":\"Ikoria: Lair of Behemoths Promos\",\"code\":\"piko\"},{\"name\":\"Ikoria: Lair of Behemoths Tokens\",\"code\":\"tiko\"},{\"name\":\"Ikoria: Lair of Behemoths\",\"code\":\"iko\"},{\"name\":\"Commander 2020 Tokens\",\"code\":\"tc20\"},{\"name\":\"Commander 2020\",\"code\":\"c20\"},{\"name\":\"Historic Anthology 2\",\"code\":\"ha2\"},{\"name\":\"Mystery Booster Retail Edition Foils\",\"code\":\"fmb1\"},{\"name\":\"Unsanctioned Tokens\",\"code\":\"tund\"},{\"name\":\"Unsanctioned\",\"code\":\"und\"},{\"name\":\"Theros Beyond Death Promos\",\"code\":\"pthb\"},{\"name\":\"Theros Beyond Death Tokens\",\"code\":\"tthb\"},{\"name\":\"Theros Beyond Death\",\"code\":\"thb\"},{\"name\":\"Judge Gift Cards 2020\",\"code\":\"j20\"},{\"name\":\"MagicFest 2020\",\"code\":\"pf20\"},{\"name\":\"Secret Lair Promos\",\"code\":\"psld\"},{\"name\":\"Secret Lair Drop Series\",\"code\":\"sld\"},{\"name\":\"Historic Anthology 1\",\"code\":\"ha1\"},{\"name\":\"Game Night 2019 Tokens\",\"code\":\"tgn2\"},{\"name\":\"Game Night 2019\",\"code\":\"gn2\"},{\"name\":\"Mystery Booster Playtest Cards\",\"code\":\"cmb1\"},{\"name\":\"Mystery Booster\",\"code\":\"mb1\"},{\"name\":\"Ponies: The Galloping\",\"code\":\"ptg\"},{\"name\":\"Throne of Eldraine Promos\",\"code\":\"peld\"},{\"name\":\"ELD Collector Boosters\",\"code\":\"celd\"},{\"name\":\"Throne of Eldraine\",\"code\":\"eld\"},{\"name\":\"Commander 2019 Oversized\",\"code\":\"oc19\"},{\"name\":\"Commander 2019\",\"code\":\"c19\"},{\"name\":\"Commander 2019 Tokens\",\"code\":\"tc19\"},{\"name\":\"Commander 2019\",\"code\":\"c19\"},{\"name\":\"San Diego Comic-Con 2019\",\"code\":\"ps19\"},{\"name\":\"Core Set 2020 Promos\",\"code\":\"pm20\"},{\"name\":\"M20 Promo Packs\",\"code\":\"ppp1\"},{\"name\":\"Core Set 2020 Tokens\",\"code\":\"tm20\"},{\"name\":\"Core Set 2020\",\"code\":\"m20\"},{\"name\":\"Signature Spellbook: Gideon\",\"code\":\"ss2\"},{\"name\":\"Modern Horizons Promos\",\"code\":\"pmh1\"},{\"name\":\"Modern Horizons\",\"code\":\"mh1\"},{\"name\":\"Modern Horizons Tokens\",\"code\":\"tmh1\"},{\"name\":\"War of the Spark Tokens\",\"code\":\"twar\"},{\"name\":\"War of the Spark\",\"code\":\"war\"},{\"name\":\"Judge Gift Cards 2019\",\"code\":\"j19\"},{\"name\":\"War of the Spark Promos\",\"code\":\"pwar\"},{\"name\":\"RNA Ravnica Weekend\",\"code\":\"prw2\"},{\"name\":\"RNA Guild Kit\",\"code\":\"gk2\"},{\"name\":\"RNA Guild Kit Tokens\",\"code\":\"tgk2\"},{\"name\":\"Ravnica Allegiance Promos\",\"code\":\"prna\"},{\"name\":\"Ravnica Allegiance\",\"code\":\"rna\"},{\"name\":\"Ravnica Allegiance Tokens\",\"code\":\"trna\"},{\"name\":\"MagicFest 2019\",\"code\":\"pf19\"},{\"name\":\"Planechase Anthology Planes\",\"code\":\"opca\"},{\"name\":\"Ultimate Box Topper\",\"code\":\"puma\"},{\"name\":\"Ultimate Masters\",\"code\":\"uma\"},{\"name\":\"Ultimate Masters Tokens\",\"code\":\"tuma\"},{\"name\":\"Game Night\",\"code\":\"gnt\"},{\"name\":\"M19 Gift Pack\",\"code\":\"g18\"},{\"name\":\"GRN Guild Kit Tokens\",\"code\":\"tgk1\"},{\"name\":\"GRN Guild Kit\",\"code\":\"gk1\"},{\"name\":\"Guilds of Ravnica Promos\",\"code\":\"pgrn\"},{\"name\":\"Guilds of Ravnica Tokens\",\"code\":\"tgrn\"},{\"name\":\"Guilds of Ravnica\",\"code\":\"grn\"},{\"name\":\"GRN Ravnica Weekend\",\"code\":\"prwk\"},{\"name\":\"Mythic Edition Tokens\",\"code\":\"tmed\"},{\"name\":\"Mythic Edition\",\"code\":\"med\"},{\"name\":\"Commander 2018 Oversized\",\"code\":\"oc18\"},{\"name\":\"Commander 2018\",\"code\":\"c18\"},{\"name\":\"Commander 2018 Tokens\",\"code\":\"tc18\"},{\"name\":\"2017 Heroes of the Realm\",\"code\":\"htr17\"},{\"name\":\"San Diego Comic-Con 2018\",\"code\":\"ps18\"},{\"name\":\"Arena New Player Experience\",\"code\":\"ana\"},{\"name\":\"MTG Arena Promos\",\"code\":\"pana\"},{\"name\":\"M19 Standard Showdown\",\"code\":\"pss3\"},{\"name\":\"Core Set 2019 Promos\",\"code\":\"pm19\"},{\"name\":\"Core Set 2019\",\"code\":\"m19\"},{\"name\":\"Core Set 2019 Tokens\",\"code\":\"tm19\"},{\"name\":\"Global Series Jiang Yanggu & Mu Yanling\",\"code\":\"gs1\"},{\"name\":\"Signature Spellbook: Jace\",\"code\":\"ss1\"},{\"name\":\"Battlebond Promos\",\"code\":\"pbbd\"},{\"name\":\"Battlebond\",\"code\":\"bbd\"},{\"name\":\"Battlebond Tokens\",\"code\":\"tbbd\"},{\"name\":\"Commander Anthology Volume II Tokens\",\"code\":\"tcm2\"},{\"name\":\"Commander Anthology Volume II\",\"code\":\"cm2\"},{\"name\":\"Dominaria Tokens\",\"code\":\"tdom\"},{\"name\":\"Dominaria\",\"code\":\"dom\"},{\"name\":\"Dominaria Promos\",\"code\":\"pdom\"},{\"name\":\"Duel Decks: Elves vs. Inventors\",\"code\":\"ddu\"},{\"name\":\"Duel Decks: Elves vs. Inventors Tokens\",\"code\":\"tddu\"},{\"name\":\"Masters 25\",\"code\":\"a25\"},{\"name\":\"Masters 25 Tokens\",\"code\":\"ta25\"},{\"name\":\"2018 Lunar New Year\",\"code\":\"plny\"},{\"name\":\"Nationals Promos\",\"code\":\"pnat\"},{\"name\":\"Rivals of Ixalan Promos\",\"code\":\"prix\"},{\"name\":\"Rivals of Ixalan Tokens\",\"code\":\"trix\"},{\"name\":\"Rivals of Ixalan\",\"code\":\"rix\"},{\"name\":\"Judge Gift Cards 2018\",\"code\":\"j18\"},{\"name\":\"Friday Night Magic 2018\",\"code\":\"f18\"},{\"name\":\"Unstable\",\"code\":\"ust\"},{\"name\":\"Iconic Masters Tokens\",\"code\":\"tima\"},{\"name\":\"XLN Treasure Chest\",\"code\":\"pxtc\"},{\"name\":\"From the Vault: Transform\",\"code\":\"v17\"},{\"name\":\"Explorers of Ixalan\",\"code\":\"e02\"},{\"name\":\"Iconic Masters\",\"code\":\"ima\"},{\"name\":\"Unstable Tokens\",\"code\":\"tust\"},{\"name\":\"Unstable Promos\",\"code\":\"pust\"},{\"name\":\"Duel Decks: Merfolk vs. Goblins\",\"code\":\"ddt\"},{\"name\":\"Duel Decks: Merfolk vs. Goblins Tokens\",\"code\":\"tddt\"},{\"name\":\"2017 Gift Pack\",\"code\":\"g17\"},{\"name\":\"Ixalan\",\"code\":\"xln\"},{\"name\":\"Ixalan Tokens\",\"code\":\"txln\"},{\"name\":\"Ixalan Promos\",\"code\":\"pxln\"},{\"name\":\"XLN Standard Showdown\",\"code\":\"pss2\"},{\"name\":\"HasCon 2017\",\"code\":\"h17\"},{\"name\":\"2016 Heroes of the Realm\",\"code\":\"htr\"},{\"name\":\"Archenemy: Nicol Bolas Tokens\",\"code\":\"te01\"},{\"name\":\"Commander 2017 Oversized\",\"code\":\"oc17\"},{\"name\":\"Commander 2017\",\"code\":\"c17\"},{\"name\":\"Commander 2017 Tokens\",\"code\":\"tc17\"},{\"name\":\"San Diego Comic-Con 2017\",\"code\":\"ps17\"},{\"name\":\"Hour of Devastation\",\"code\":\"hou\"},{\"name\":\"Hour of Devastation Promos\",\"code\":\"phou\"},{\"name\":\"Hour of Devastation Tokens\",\"code\":\"thou\"},{\"name\":\"Archenemy: Nicol Bolas Schemes\",\"code\":\"oe01\"},{\"name\":\"Archenemy: Nicol Bolas\",\"code\":\"e01\"},{\"name\":\"Commander Anthology Tokens\",\"code\":\"tcma\"},{\"name\":\"Commander Anthology\",\"code\":\"cma\"},{\"name\":\"Amonkhet\",\"code\":\"akh\"},{\"name\":\"Amonkhet Promos\",\"code\":\"pakh\"},{\"name\":\"Amonkhet Tokens\",\"code\":\"takh\"},{\"name\":\"Amonkhet Invocations\",\"code\":\"mp2\"},{\"name\":\"Welcome Deck 2017\",\"code\":\"w17\"},{\"name\":\"Duel Decks: Mind vs. Might\",\"code\":\"dds\"},{\"name\":\"Duel Decks: Mind vs. Might Tokens\",\"code\":\"tdds\"},{\"name\":\"Modern Masters 2017 Tokens\",\"code\":\"tmm3\"},{\"name\":\"Modern Masters 2017\",\"code\":\"mm3\"},{\"name\":\"Aether Revolt Tokens\",\"code\":\"taer\"},{\"name\":\"Aether Revolt\",\"code\":\"aer\"},{\"name\":\"Aether Revolt Promos\",\"code\":\"paer\"},{\"name\":\"League Tokens 2017\",\"code\":\"l17\"},{\"name\":\"Judge Gift Cards 2017\",\"code\":\"j17\"},{\"name\":\"Friday Night Magic 2017\",\"code\":\"f17\"},{\"name\":\"Planechase Anthology\",\"code\":\"pca\"},{\"name\":\"Planechase Anthology Tokens\",\"code\":\"tpca\"},{\"name\":\"Treasure Chest\",\"code\":\"pz2\"},{\"name\":\"Commander 2016 Oversized\",\"code\":\"oc16\"},{\"name\":\"Commander 2016\",\"code\":\"c16\"},{\"name\":\"Commander 2016 Tokens\",\"code\":\"tc16\"},{\"name\":\"San Diego Comic-Con 2016\",\"code\":\"ps16\"},{\"name\":\"Kaladesh\",\"code\":\"kld\"},{\"name\":\"Kaladesh Tokens\",\"code\":\"tkld\"},{\"name\":\"Kaladesh Promos\",\"code\":\"pkld\"},{\"name\":\"Kaladesh Inventions\",\"code\":\"mps\"},{\"name\":\"Duel Decks: Nissa vs. Ob Nixilis\",\"code\":\"ddr\"},{\"name\":\"Conspiracy: Take the Crown Tokens\",\"code\":\"tcn2\"},{\"name\":\"Conspiracy: Take the Crown\",\"code\":\"cn2\"},{\"name\":\"From the Vault: Lore\",\"code\":\"v16\"},{\"name\":\"Eldritch Moon Tokens\",\"code\":\"temn\"},{\"name\":\"Eldritch Moon\",\"code\":\"emn\"},{\"name\":\"Eldritch Moon Promos\",\"code\":\"pemn\"},{\"name\":\"Eternal Masters\",\"code\":\"ema\"},{\"name\":\"Eternal Masters Tokens\",\"code\":\"tema\"},{\"name\":\"Shadows over Innistrad Tokens\",\"code\":\"tsoi\"},{\"name\":\"Shadows over Innistrad\",\"code\":\"soi\"},{\"name\":\"Shadows over Innistrad Promos\",\"code\":\"psoi\"},{\"name\":\"Welcome Deck 2016\",\"code\":\"w16\"},{\"name\":\"Duel Decks: Blessed vs. Cursed\",\"code\":\"ddq\"},{\"name\":\"Oath of the Gatewatch Tokens\",\"code\":\"togw\"},{\"name\":\"Oath of the Gatewatch\",\"code\":\"ogw\"},{\"name\":\"Oath of the Gatewatch Promos\",\"code\":\"pogw\"},{\"name\":\"League Tokens 2016\",\"code\":\"l16\"},{\"name\":\"Friday Night Magic 2016\",\"code\":\"f16\"},{\"name\":\"Judge Gift Cards 2016\",\"code\":\"j16\"},{\"name\":\"Legendary Cube Prize Pack\",\"code\":\"pz1\"},{\"name\":\"Commander 2015\",\"code\":\"c15\"},{\"name\":\"Commander 2015 Tokens\",\"code\":\"tc15\"},{\"name\":\"Commander 2015 Oversized\",\"code\":\"oc15\"},{\"name\":\"Battle for Zendikar\",\"code\":\"bfz\"},{\"name\":\"Battle for Zendikar Tokens\",\"code\":\"tbfz\"},{\"name\":\"BFZ Standard Series\",\"code\":\"pss1\"},{\"name\":\"Zendikar Expeditions\",\"code\":\"exp\"},{\"name\":\"Battle for Zendikar Promos\",\"code\":\"pbfz\"},{\"name\":\"Duel Decks: Zendikar vs. Eldrazi\",\"code\":\"ddp\"},{\"name\":\"From the Vault: Angels\",\"code\":\"v15\"},{\"name\":\"Magic Origins Clash Pack\",\"code\":\"cp3\"},{\"name\":\"Magic Origins Promos\",\"code\":\"pori\"},{\"name\":\"Magic Origins\",\"code\":\"ori\"},{\"name\":\"Magic Origins Tokens\",\"code\":\"tori\"},{\"name\":\"San Diego Comic-Con 2015\",\"code\":\"ps15\"},{\"name\":\"Modern Masters 2015 Tokens\",\"code\":\"tmm2\"},{\"name\":\"Modern Masters 2015\",\"code\":\"mm2\"},{\"name\":\"Tempest Remastered\",\"code\":\"tpr\"},{\"name\":\"Tarkir Dragonfury\",\"code\":\"ptkdf\"},{\"name\":\"Dragons of Tarkir Tokens\",\"code\":\"tdtk\"},{\"name\":\"Dragons of Tarkir\",\"code\":\"dtk\"},{\"name\":\"Dragons of Tarkir Promos\",\"code\":\"pdtk\"},{\"name\":\"Duel Decks: Elspeth vs. Kiora\",\"code\":\"ddo\"},{\"name\":\"Fate Reforged Promos\",\"code\":\"pfrf\"},{\"name\":\"Fate Reforged Clash Pack\",\"code\":\"cp2\"},{\"name\":\"Fate Reforged Tokens\",\"code\":\"tfrf\"},{\"name\":\"Fate Reforged\",\"code\":\"frf\"},{\"name\":\"Ugin\'s Fate\",\"code\":\"ugin\"},{\"name\":\"League Tokens 2015\",\"code\":\"l15\"},{\"name\":\"Judge Gift Cards 2015\",\"code\":\"j15\"},{\"name\":\"Friday Night Magic 2015\",\"code\":\"f15\"},{\"name\":\"Duel Decks Anthology: Jace vs. Chandra Tokens\",\"code\":\"tjvc\"},{\"name\":\"Duel Decks Anthology: Divine vs. Demonic Tokens\",\"code\":\"tdvd\"},{\"name\":\"Duel Decks Anthology: Garruk vs. Liliana Tokens\",\"code\":\"tgvl\"},{\"name\":\"Duel Decks Anthology: Jace vs. Chandra\",\"code\":\"jvc\"},{\"name\":\"Duel Decks Anthology: Garruk vs. Liliana\",\"code\":\"gvl\"},{\"name\":\"Duel Decks Anthology: Elves vs. Goblins Tokens\",\"code\":\"tevg\"},{\"name\":\"Duel Decks Anthology: Divine vs. Demonic\",\"code\":\"dvd\"},{\"name\":\"Duel Decks Anthology: Elves vs. Goblins\",\"code\":\"evg\"},{\"name\":\"Commander 2014 Oversized\",\"code\":\"oc14\"},{\"name\":\"Commander 2014 Tokens\",\"code\":\"tc14\"},{\"name\":\"Commander 2014\",\"code\":\"c14\"},{\"name\":\"Khans of Tarkir Tokens\",\"code\":\"tktk\"},{\"name\":\"Khans of Tarkir\",\"code\":\"ktk\"},{\"name\":\"Khans of Tarkir Promos\",\"code\":\"pktk\"},{\"name\":\"Duel Decks: Speed vs. Cunning\",\"code\":\"ddn\"},{\"name\":\"From the Vault: Annihilation\",\"code\":\"v14\"},{\"name\":\"Magic 2015 Clash Pack\",\"code\":\"cp1\"},{\"name\":\"Magic 2015\",\"code\":\"m15\"},{\"name\":\"Magic 2015 Tokens\",\"code\":\"tm15\"},{\"name\":\"Magic 2015 Promos\",\"code\":\"pm15\"},{\"name\":\"M15 Prerelease Challenge\",\"code\":\"ppc1\"},{\"name\":\"San Diego Comic-Con 2014\",\"code\":\"ps14\"},{\"name\":\"Vintage Masters\",\"code\":\"vma\"},{\"name\":\"Conspiracy\",\"code\":\"cns\"},{\"name\":\"Conspiracy Tokens\",\"code\":\"tcns\"},{\"name\":\"Modern Event Deck 2014 Tokens\",\"code\":\"tmd1\"},{\"name\":\"Modern Event Deck 2014\",\"code\":\"md1\"},{\"name\":\"Defeat a God\",\"code\":\"tdag\"},{\"name\":\"Journey into Nyx\",\"code\":\"jou\"},{\"name\":\"Journey into Nyx Tokens\",\"code\":\"tjou\"},{\"name\":\"Journey into Nyx Hero\'s Path\",\"code\":\"thp3\"},{\"name\":\"Journey into Nyx Promos\",\"code\":\"pjou\"},{\"name\":\"Duel Decks: Jace vs. Vraska Tokens\",\"code\":\"tddm\"},{\"name\":\"Duel Decks: Jace vs. Vraska\",\"code\":\"ddm\"},{\"name\":\"Battle the Horde\",\"code\":\"tbth\"},{\"name\":\"Born of the Gods Hero\'s Path\",\"code\":\"thp2\"},{\"name\":\"Born of the Gods\",\"code\":\"bng\"},{\"name\":\"Born of the Gods Tokens\",\"code\":\"tbng\"},{\"name\":\"Born of the Gods Promos\",\"code\":\"pbng\"},{\"name\":\"Duels of the Planeswalkers Promos 2014\",\"code\":\"pdp14\"},{\"name\":\"IDW Comics 2014\",\"code\":\"pi14\"},{\"name\":\"League Tokens 2014\",\"code\":\"l14\"},{\"name\":\"Friday Night Magic 2014\",\"code\":\"f14\"},{\"name\":\"Judge Gift Cards 2014\",\"code\":\"j14\"},{\"name\":\"Commander 2013 Oversized\",\"code\":\"oc13\"},{\"name\":\"Commander 2013\",\"code\":\"c13\"},{\"name\":\"Face the Hydra\",\"code\":\"tfth\"},{\"name\":\"Theros\",\"code\":\"ths\"},{\"name\":\"Theros Hero\'s Path\",\"code\":\"thp1\"},{\"name\":\"Theros Tokens\",\"code\":\"tths\"},{\"name\":\"Theros Promos\",\"code\":\"pths\"},{\"name\":\"Duel Decks: Heroes vs. Monsters Tokens\",\"code\":\"tddl\"},{\"name\":\"Duel Decks: Heroes vs. Monsters\",\"code\":\"ddl\"},{\"name\":\"From the Vault: Twenty\",\"code\":\"v13\"},{\"name\":\"Magic 2014 Tokens\",\"code\":\"tm14\"},{\"name\":\"Magic 2014\",\"code\":\"m14\"},{\"name\":\"Magic 2014 Promos\",\"code\":\"pm14\"},{\"name\":\"San Diego Comic-Con 2013\",\"code\":\"psdc\"},{\"name\":\"Modern Masters Tokens\",\"code\":\"tmma\"},{\"name\":\"Modern Masters\",\"code\":\"mma\"},{\"name\":\"Dragon\'s Maze\",\"code\":\"dgm\"},{\"name\":\"Dragon\'s Maze Tokens\",\"code\":\"tdgm\"},{\"name\":\"Dragon\'s Maze Promos\",\"code\":\"pdgm\"},{\"name\":\"World Magic Cup Qualifiers\",\"code\":\"pwcq\"},{\"name\":\"Duel Decks: Sorin vs. Tibalt\",\"code\":\"ddk\"},{\"name\":\"Duel Decks: Sorin vs. Tibalt Tokens\",\"code\":\"tddk\"},{\"name\":\"Gatecrash\",\"code\":\"gtc\"},{\"name\":\"Gatecrash Tokens\",\"code\":\"tgtc\"},{\"name\":\"Gatecrash Promos\",\"code\":\"pgtc\"},{\"name\":\"Duels of the Planeswalkers Promos 2013\",\"code\":\"pdp13\"},{\"name\":\"IDW Comics 2013\",\"code\":\"pi13\"},{\"name\":\"League Tokens 2013\",\"code\":\"l13\"},{\"name\":\"Judge Gift Cards 2013\",\"code\":\"j13\"},{\"name\":\"Friday Night Magic 2013\",\"code\":\"f13\"},{\"name\":\"Commander\'s Arsenal Oversized\",\"code\":\"ocm1\"},{\"name\":\"Commander\'s Arsenal\",\"code\":\"cm1\"},{\"name\":\"Return to Ravnica\",\"code\":\"rtr\"},{\"name\":\"Return to Ravnica Promos\",\"code\":\"prtr\"},{\"name\":\"Return to Ravnica Tokens\",\"code\":\"trtr\"},{\"name\":\"Duel Decks: Izzet vs. Golgari\",\"code\":\"ddj\"},{\"name\":\"Duel Decks: Izzet vs. Golgari Tokens\",\"code\":\"tddj\"},{\"name\":\"From the Vault: Realms\",\"code\":\"v12\"},{\"name\":\"Magic 2013\",\"code\":\"m13\"},{\"name\":\"Magic 2013 Tokens\",\"code\":\"tm13\"},{\"name\":\"Magic 2013 Promos\",\"code\":\"pm13\"},{\"name\":\"Planechase 2012 Planes\",\"code\":\"opc2\"},{\"name\":\"Planechase 2012\",\"code\":\"pc2\"},{\"name\":\"Avacyn Restored Tokens\",\"code\":\"tavr\"},{\"name\":\"Avacyn Restored\",\"code\":\"avr\"},{\"name\":\"Open the Helvault\",\"code\":\"phel\"},{\"name\":\"Avacyn Restored Promos\",\"code\":\"pavr\"},{\"name\":\"Duel Decks: Venser vs. Koth Tokens\",\"code\":\"tddi\"},{\"name\":\"Duel Decks: Venser vs. Koth\",\"code\":\"ddi\"},{\"name\":\"Dark Ascension\",\"code\":\"dka\"},{\"name\":\"Dark Ascension Tokens\",\"code\":\"tdka\"},{\"name\":\"Dark Ascension Promos\",\"code\":\"pdka\"},{\"name\":\"IDW Comics 2012\",\"code\":\"pidw\"},{\"name\":\"Wizards Play Network 2012\",\"code\":\"pwp12\"},{\"name\":\"Duels of the Planeswalkers Promos 2012\",\"code\":\"pdp12\"},{\"name\":\"League Tokens 2012\",\"code\":\"l12\"},{\"name\":\"Judge Gift Cards 2012\",\"code\":\"j12\"},{\"name\":\"Friday Night Magic 2012\",\"code\":\"f12\"},{\"name\":\"Premium Deck Series: Graveborn\",\"code\":\"pd3\"},{\"name\":\"Innistrad Tokens\",\"code\":\"tisd\"},{\"name\":\"Innistrad\",\"code\":\"isd\"},{\"name\":\"Innistrad Promos\",\"code\":\"pisd\"},{\"name\":\"Duel Decks: Ajani vs. Nicol Bolas\",\"code\":\"ddh\"},{\"name\":\"Duel Decks: Ajani vs. Nicol Bolas Tokens\",\"code\":\"tddh\"},{\"name\":\"From the Vault: Legends\",\"code\":\"v11\"},{\"name\":\"Magic 2012 Tokens\",\"code\":\"tm12\"},{\"name\":\"Magic 2012\",\"code\":\"m12\"},{\"name\":\"Magic 2012 Promos\",\"code\":\"pm12\"},{\"name\":\"Commander 2011 Oversized\",\"code\":\"ocmd\"},{\"name\":\"Commander 2011\",\"code\":\"cmd\"},{\"name\":\"Commander 2011 Launch Party\",\"code\":\"pcmd\"},{\"name\":\"Duel Decks: Mirrodin Pure vs. New Phyrexia\",\"code\":\"td2\"},{\"name\":\"New Phyrexia Tokens\",\"code\":\"tnph\"},{\"name\":\"New Phyrexia\",\"code\":\"nph\"},{\"name\":\"New Phyrexia Promos\",\"code\":\"pnph\"},{\"name\":\"Duel Decks: Knights vs. Dragons\",\"code\":\"ddg\"},{\"name\":\"Duel Decks: Knights vs. Dragons Tokens\",\"code\":\"tddg\"},{\"name\":\"Mirrodin Besieged Tokens\",\"code\":\"tmbs\"},{\"name\":\"Mirrodin Besieged\",\"code\":\"mbs\"},{\"name\":\"Mirrodin Besieged Promos\",\"code\":\"pmbs\"},{\"name\":\"Masters Edition IV\",\"code\":\"me4\"},{\"name\":\"Magic Premiere Shop 2011\",\"code\":\"pmps11\"},{\"name\":\"Duels of the Planeswalkers Promos 2011\",\"code\":\"pdp11\"},{\"name\":\"Wizards Play Network 2011\",\"code\":\"pwp11\"},{\"name\":\"Friday Night Magic 2011\",\"code\":\"f11\"},{\"name\":\"Salvat 2011\",\"code\":\"ps11\"},{\"name\":\"Judge Gift Cards 2011\",\"code\":\"g11\"},{\"name\":\"Magic Player Rewards 2011\",\"code\":\"p11\"},{\"name\":\"Legacy Championship\",\"code\":\"olgc\"},{\"name\":\"Premium Deck Series: Fire and Lightning\",\"code\":\"pd2\"},{\"name\":\"Magic Online Theme Decks\",\"code\":\"td0\"},{\"name\":\"Scars of Mirrodin Tokens\",\"code\":\"tsom\"},{\"name\":\"Scars of Mirrodin\",\"code\":\"som\"},{\"name\":\"Scars of Mirrodin Promos\",\"code\":\"psom\"},{\"name\":\"Duel Decks: Elspeth vs. Tezzeret\",\"code\":\"ddf\"},{\"name\":\"Duel Decks: Elspeth vs. Tezzeret Tokens\",\"code\":\"tddf\"},{\"name\":\"From the Vault: Relics\",\"code\":\"v10\"},{\"name\":\"Magic 2011 Tokens\",\"code\":\"tm11\"},{\"name\":\"Magic 2011\",\"code\":\"m11\"},{\"name\":\"Magic 2011 Promos\",\"code\":\"pm11\"},{\"name\":\"Archenemy Schemes\",\"code\":\"oarc\"},{\"name\":\"Archenemy\",\"code\":\"arc\"},{\"name\":\"Promotional Schemes\",\"code\":\"parc\"},{\"name\":\"Duels of the Planeswalkers\",\"code\":\"dpa\"},{\"name\":\"Rise of the Eldrazi Promos\",\"code\":\"proe\"},{\"name\":\"Rise of the Eldrazi Tokens\",\"code\":\"troe\"},{\"name\":\"Rise of the Eldrazi\",\"code\":\"roe\"},{\"name\":\"Duel Decks: Phyrexia vs. the Coalition Tokens\",\"code\":\"tdde\"},{\"name\":\"Duel Decks: Phyrexia vs. the Coalition\",\"code\":\"dde\"},{\"name\":\"Worldwake Promos\",\"code\":\"pwwk\"},{\"name\":\"Worldwake\",\"code\":\"wwk\"},{\"name\":\"Worldwake Tokens\",\"code\":\"twwk\"},{\"name\":\"Duels of the Planeswalkers Promos 2010\",\"code\":\"pdp10\"},{\"name\":\"Wizards Play Network 2010\",\"code\":\"pwp10\"},{\"name\":\"Magic Premiere Shop 2010\",\"code\":\"pmps10\"},{\"name\":\"Friday Night Magic 2010\",\"code\":\"f10\"},{\"name\":\"Magic Player Rewards 2010\",\"code\":\"p10\"},{\"name\":\"Judge Gift Cards 2010\",\"code\":\"g10\"},{\"name\":\"Premium Deck Series: Slivers\",\"code\":\"h09\"},{\"name\":\"Duel Decks: Garruk vs. Liliana\",\"code\":\"ddd\"},{\"name\":\"Duel Decks: Garruk vs. Liliana Tokens\",\"code\":\"tddd\"},{\"name\":\"Zendikar Promos\",\"code\":\"pzen\"},{\"name\":\"Zendikar\",\"code\":\"zen\"},{\"name\":\"Zendikar Tokens\",\"code\":\"tzen\"},{\"name\":\"Masters Edition III\",\"code\":\"me3\"},{\"name\":\"Planechase Planes\",\"code\":\"ohop\"},{\"name\":\"Planechase\",\"code\":\"hop\"},{\"name\":\"Promotional Planes\",\"code\":\"phop\"},{\"name\":\"From the Vault: Exiled\",\"code\":\"v09\"},{\"name\":\"Magic 2010 Tokens\",\"code\":\"tm10\"},{\"name\":\"Magic 2010\",\"code\":\"m10\"},{\"name\":\"Magic 2010 Promos\",\"code\":\"pm10\"},{\"name\":\"Alara Reborn Tokens\",\"code\":\"tarb\"},{\"name\":\"Alara Reborn\",\"code\":\"arb\"},{\"name\":\"Duel Decks: Divine vs. Demonic\",\"code\":\"ddc\"},{\"name\":\"Duel Decks: Divine vs. Demonic Tokens\",\"code\":\"tddc\"},{\"name\":\"URL: Convention Promos\",\"code\":\"purl\"},{\"name\":\"Conflux\",\"code\":\"con\"},{\"name\":\"Conflux Tokens\",\"code\":\"tcon\"},{\"name\":\"Miscellaneous Book Promos\",\"code\":\"pbok\"},{\"name\":\"Wizards Play Network 2009\",\"code\":\"pwp09\"},{\"name\":\"Duels of the Planeswalkers Promos 2009\",\"code\":\"pdtp\"},{\"name\":\"Magic Premiere Shop 2009\",\"code\":\"pmps09\"},{\"name\":\"Magic Player Rewards 2009\",\"code\":\"p09\"},{\"name\":\"Friday Night Magic 2009\",\"code\":\"f09\"},{\"name\":\"Judge Gift Cards 2009\",\"code\":\"g09\"},{\"name\":\"Duel Decks: Jace vs. Chandra\",\"code\":\"dd2\"},{\"name\":\"Duel Decks: Jace vs. Chandra Tokens\",\"code\":\"tdd2\"},{\"name\":\"Shards of Alara Tokens\",\"code\":\"tala\"},{\"name\":\"Shards of Alara\",\"code\":\"ala\"},{\"name\":\"Wizards Play Network 2008\",\"code\":\"pwpn\"},{\"name\":\"Masters Edition II\",\"code\":\"me2\"},{\"name\":\"From the Vault: Dragons\",\"code\":\"drb\"},{\"name\":\"Eventide\",\"code\":\"eve\"},{\"name\":\"Eventide Tokens\",\"code\":\"teve\"},{\"name\":\"Shadowmoor Tokens\",\"code\":\"tshm\"},{\"name\":\"Shadowmoor\",\"code\":\"shm\"},{\"name\":\"15th Anniversary Cards\",\"code\":\"p15a\"},{\"name\":\"Morningtide\",\"code\":\"mor\"},{\"name\":\"Morningtide Tokens\",\"code\":\"tmor\"},{\"name\":\"Launch Parties\",\"code\":\"plpa\"},{\"name\":\"Magic Premiere Shop 2008\",\"code\":\"pmps08\"},{\"name\":\"Gateway 2008\",\"code\":\"pg08\"},{\"name\":\"Friday Night Magic 2008\",\"code\":\"f08\"},{\"name\":\"Judge Gift Cards 2008\",\"code\":\"g08\"},{\"name\":\"Magic Player Rewards 2008\",\"code\":\"p08\"},{\"name\":\"Duel Decks: Elves vs. Goblins Tokens\",\"code\":\"tdd1\"},{\"name\":\"Duel Decks: Elves vs. Goblins\",\"code\":\"dd1\"},{\"name\":\"Lorwyn Tokens\",\"code\":\"tlrw\"},{\"name\":\"Lorwyn\",\"code\":\"lrw\"},{\"name\":\"Masters Edition\",\"code\":\"me1\"},{\"name\":\"Summer of Magic\",\"code\":\"psum\"},{\"name\":\"Tenth Edition\",\"code\":\"10e\"},{\"name\":\"Tenth Edition Promos\",\"code\":\"p10e\"},{\"name\":\"Tenth Edition Tokens\",\"code\":\"t10e\"},{\"name\":\"Future Sight\",\"code\":\"fut\"},{\"name\":\"Grand Prix Promos\",\"code\":\"pgpx\"},{\"name\":\"Pro Tour Promos\",\"code\":\"ppro\"},{\"name\":\"Planar Chaos\",\"code\":\"plc\"},{\"name\":\"Resale Promos\",\"code\":\"pres\"},{\"name\":\"Gateway 2007\",\"code\":\"pg07\"},{\"name\":\"Magic Premiere Shop 2007\",\"code\":\"pmps07\"},{\"name\":\"Magic Player Rewards 2007\",\"code\":\"p07\"},{\"name\":\"Judge Gift Cards 2007\",\"code\":\"g07\"},{\"name\":\"Friday Night Magic 2007\",\"code\":\"f07\"},{\"name\":\"Happy Holidays\",\"code\":\"hho\"},{\"name\":\"Time Spiral\",\"code\":\"tsp\"},{\"name\":\"Time Spiral Timeshifted\",\"code\":\"tsb\"},{\"name\":\"Coldsnap Tokens\",\"code\":\"tcsp\"},{\"name\":\"Coldsnap\",\"code\":\"csp\"},{\"name\":\"Coldsnap Theme Decks\",\"code\":\"cst\"},{\"name\":\"Dissension\",\"code\":\"dis\"},{\"name\":\"Champs and States\",\"code\":\"pcmp\"},{\"name\":\"Guildpact\",\"code\":\"gpt\"},{\"name\":\"Arena League 2006\",\"code\":\"pal06\"},{\"name\":\"Magic Premiere Shop 2006\",\"code\":\"pmps06\"},{\"name\":\"Junior APAC Series\",\"code\":\"pjas\"},{\"name\":\"Judge Gift Cards 2006\",\"code\":\"g06\"},{\"name\":\"Hachette UK\",\"code\":\"phuk\"},{\"name\":\"Magic Player Rewards 2006\",\"code\":\"p06\"},{\"name\":\"Gateway 2006\",\"code\":\"pgtw\"},{\"name\":\"Friday Night Magic 2006\",\"code\":\"f06\"},{\"name\":\"Two-Headed Giant Tournament\",\"code\":\"p2hg\"},{\"name\":\"Ravnica: City of Guilds\",\"code\":\"rav\"},{\"name\":\"Salvat 2005\",\"code\":\"psal\"},{\"name\":\"Ninth Edition\",\"code\":\"9ed\"},{\"name\":\"Saviors of Kamigawa\",\"code\":\"sok\"},{\"name\":\"Betrayers of Kamigawa\",\"code\":\"bok\"},{\"name\":\"Magic Premiere Shop 2005\",\"code\":\"pmps\"},{\"name\":\"Arena League 2005\",\"code\":\"pal05\"},{\"name\":\"Junior Series Europe\",\"code\":\"pjse\"},{\"name\":\"Friday Night Magic 2005\",\"code\":\"f05\"},{\"name\":\"Judge Gift Cards 2005\",\"code\":\"g05\"},{\"name\":\"Magic Player Rewards 2005\",\"code\":\"p05\"},{\"name\":\"Unhinged\",\"code\":\"unh\"},{\"name\":\"Champions of Kamigawa\",\"code\":\"chk\"},{\"name\":\"World Championship Decks 2004\",\"code\":\"wc04\"},{\"name\":\"Fifth Dawn\",\"code\":\"5dn\"},{\"name\":\"Darksteel\",\"code\":\"dst\"},{\"name\":\"Arena League 2004\",\"code\":\"pal04\"},{\"name\":\"Magic Player Rewards 2004\",\"code\":\"p04\"},{\"name\":\"Judge Gift Cards 2004\",\"code\":\"g04\"},{\"name\":\"Friday Night Magic 2004\",\"code\":\"f04\"},{\"name\":\"Mirrodin\",\"code\":\"mrd\"},{\"name\":\"World Championship Decks 2003\",\"code\":\"wc03\"},{\"name\":\"Eighth Edition\",\"code\":\"8ed\"},{\"name\":\"Release Events\",\"code\":\"prel\"},{\"name\":\"Scourge\",\"code\":\"scg\"},{\"name\":\"Legions\",\"code\":\"lgn\"},{\"name\":\"Magic Online Avatars\",\"code\":\"pmoa\"},{\"name\":\"Japan Junior Tournament\",\"code\":\"pjjt\"},{\"name\":\"Arena League 2003\",\"code\":\"pal03\"},{\"name\":\"Vintage Championship\",\"code\":\"ovnt\"},{\"name\":\"Friday Night Magic 2003\",\"code\":\"f03\"},{\"name\":\"Magic Player Rewards 2003\",\"code\":\"p03\"},{\"name\":\"Judge Gift Cards 2003\",\"code\":\"g03\"},{\"name\":\"Onslaught\",\"code\":\"ons\"},{\"name\":\"World Championship Decks 2002\",\"code\":\"wc02\"},{\"name\":\"Hobby Japan Promos\",\"code\":\"phj\"},{\"name\":\"Magic Online Promos\",\"code\":\"prm\"},{\"name\":\"Judgment\",\"code\":\"jud\"},{\"name\":\"Torment\",\"code\":\"tor\"},{\"name\":\"Arena League 2002\",\"code\":\"pal02\"},{\"name\":\"Judge Gift Cards 2002\",\"code\":\"g02\"},{\"name\":\"Magic Player Rewards 2002\",\"code\":\"pr2\"},{\"name\":\"Friday Night Magic 2002\",\"code\":\"f02\"},{\"name\":\"Deckmasters\",\"code\":\"dkm\"},{\"name\":\"Odyssey\",\"code\":\"ody\"},{\"name\":\"World Championship Decks 2001\",\"code\":\"wc01\"},{\"name\":\"Apocalypse\",\"code\":\"apc\"},{\"name\":\"Seventh Edition\",\"code\":\"7ed\"},{\"name\":\"Planeshift\",\"code\":\"pls\"},{\"name\":\"Arena League 2001\",\"code\":\"pal01\"},{\"name\":\"Friday Night Magic 2001\",\"code\":\"f01\"},{\"name\":\"Judge Gift Cards 2001\",\"code\":\"g01\"},{\"name\":\"Magic Player Rewards 2001\",\"code\":\"mpr\"},{\"name\":\"Invasion\",\"code\":\"inv\"},{\"name\":\"Beatdown Box Set\",\"code\":\"btd\"},{\"name\":\"World Championship Decks 2000\",\"code\":\"wc00\"},{\"name\":\"Prophecy\",\"code\":\"pcy\"},{\"name\":\"Starter 2000\",\"code\":\"s00\"},{\"name\":\"Nemesis\",\"code\":\"nem\"},{\"name\":\"European Land Program\",\"code\":\"pelp\"},{\"name\":\"Arena League 2000\",\"code\":\"pal00\"},{\"name\":\"Friday Night Magic 2000\",\"code\":\"fnm\"},{\"name\":\"Judge Gift Cards 2000\",\"code\":\"g00\"},{\"name\":\"Junior Super Series\",\"code\":\"psus\"},{\"name\":\"Battle Royale Box Set\",\"code\":\"brb\"},{\"name\":\"Mercadian Masques\",\"code\":\"mmq\"},{\"name\":\"Wizards of the Coast Online Store\",\"code\":\"pwos\"},{\"name\":\"Worlds\",\"code\":\"pwor\"},{\"name\":\"World Championship Decks 1999\",\"code\":\"wc99\"},{\"name\":\"Guru\",\"code\":\"pgru\"},{\"name\":\"Starter 1999\",\"code\":\"s99\"},{\"name\":\"Urza\'s Destiny\",\"code\":\"uds\"},{\"name\":\"Portal Three Kingdoms\",\"code\":\"ptk\"},{\"name\":\"Classic Sixth Edition\",\"code\":\"6ed\"},{\"name\":\"Urza\'s Legacy\",\"code\":\"ulg\"},{\"name\":\"Arena League 1999\",\"code\":\"pal99\"},{\"name\":\"Judge Gift Cards 1999\",\"code\":\"g99\"},{\"name\":\"Anthologies\",\"code\":\"ath\"},{\"name\":\"Urza\'s Saga\",\"code\":\"usg\"},{\"name\":\"Asia Pacific Land Program\",\"code\":\"palp\"},{\"name\":\"World Championship Decks 1998\",\"code\":\"wc98\"},{\"name\":\"Unglued Tokens\",\"code\":\"tugl\"},{\"name\":\"Unglued\",\"code\":\"ugl\"},{\"name\":\"Exodus\",\"code\":\"exo\"},{\"name\":\"Portal Second Age\",\"code\":\"p02\"},{\"name\":\"Stronghold\",\"code\":\"sth\"},{\"name\":\"Judge Gift Cards 1998\",\"code\":\"jgp\"},{\"name\":\"Tempest\",\"code\":\"tmp\"},{\"name\":\"Prerelease Events\",\"code\":\"ppre\"},{\"name\":\"World Championship Decks 1997\",\"code\":\"wc97\"},{\"name\":\"Weatherlight\",\"code\":\"wth\"},{\"name\":\"Portal\",\"code\":\"por\"},{\"name\":\"Vanguard Series\",\"code\":\"pvan\"},{\"name\":\"Portal Demo Game\",\"code\":\"ppod\"},{\"name\":\"Fifth Edition\",\"code\":\"5ed\"},{\"name\":\"Visions\",\"code\":\"vis\"},{\"name\":\"Introductory Two-Player Set\",\"code\":\"itp\"},{\"name\":\"Multiverse Gift Box\",\"code\":\"mgb\"},{\"name\":\"Mirage\",\"code\":\"mir\"},{\"name\":\"Redemption Program\",\"code\":\"pred\"},{\"name\":\"Celebration Cards\",\"code\":\"pcel\"},{\"name\":\"Arena League 1996\",\"code\":\"parl\"},{\"name\":\"Rivals Quick Start Set\",\"code\":\"rqs\"},{\"name\":\"Alliances\",\"code\":\"all\"},{\"name\":\"Pro Tour Collector Set\",\"code\":\"ptc\"},{\"name\":\"Homelands\",\"code\":\"hml\"},{\"name\":\"Renaissance\",\"code\":\"ren\"},{\"name\":\"Rinascimento\",\"code\":\"rin\"},{\"name\":\"Chronicles\",\"code\":\"chr\"},{\"name\":\"Ice Age\",\"code\":\"ice\"},{\"name\":\"Fourth Edition Foreign Black Border\",\"code\":\"4bb\"},{\"name\":\"Fourth Edition\",\"code\":\"4ed\"},{\"name\":\"DCI Legend Membership\",\"code\":\"plgm\"},{\"name\":\"Magazine Inserts\",\"code\":\"pmei\"},{\"name\":\"Fallen Empires\",\"code\":\"fem\"},{\"name\":\"HarperPrism Book Promos\",\"code\":\"phpr\"},{\"name\":\"The Dark\",\"code\":\"drk\"},{\"name\":\"Dragon Con\",\"code\":\"pdrc\"},{\"name\":\"Summer Magic v Edgar\",\"code\":\"sum\"},{\"name\":\"Legends\",\"code\":\"leg\"},{\"name\":\"Foreign Black Border\",\"code\":\"fbb\"},{\"name\":\"Revised Edition\",\"code\":\"3ed\"},{\"name\":\"Antiquities\",\"code\":\"atq\"},{\"name\":\"Arabian Nights\",\"code\":\"arn\"},{\"name\":\"Intl. Collectors’ Edition\",\"code\":\"cei\"},{\"name\":\"Collectors’ Edition\",\"code\":\"ced\"},{\"name\":\"Unlimited Edition\",\"code\":\"2ed\"},{\"name\":\"Limited Edition Beta\",\"code\":\"leb\"},{\"name\":\"Limited Edition Alpha\",\"code\":\"lea\"}\]"
260
261-- set cards from Boosters
262booster = {}
263
264-- pack obj
265packNumber = 0
266draftSet = "m21"
267
268-- Jumpstart
269jmp = {
270 decks = {
271 {name="Above the Clouds 1", text=[[
2721 Inniaz, the Gale Force
2731 Keen Glidemaster
2741 Mistral Singer
2751 Roaming Ghostlight
2761 Tide Skimmer
2771 Wall of Runes
2781 Warden of Evos Isle
2791 Lofty Denial
2801 Rain of Revelation
2811 Rookie Mistake
2821 Unsubstantiate
2831 Capture Sphere
2841 Thriving Isle
2857 Island]]},{name="Above the Clouds 2", text=[[
2861 Inniaz, the Gale Force
2871 Keen Glidemaster
2881 Mistral Singer
2891 Roaming Ghostlight
2901 Serendib Efreet
2911 Tide Skimmer
2921 Wall of Runes
2931 Frost Breath
2941 Lofty Denial
2951 Rain of Revelation
2961 Unsubstantiate
2971 Talrand's Invocation
2981 Capture Sphere
2991 Thriving Isle
3006 Island]]},{name="Above the Clouds 3", text=[[
3011 Keen Glidemaster
3021 Roaming Ghostlight
3031 Tide Skimmer
3041 Wall of Runes
3051 Warden of Evos Isle
3061 Windreader Sphinx
3071 Frost Breath
3081 Lofty Denial
3091 Rain of Revelation
3101 Unsubstantiate
3111 Capture Sphere
3121 Thriving Isle
3138 Island]]},{name="Above the Clouds 4", text=[[
3141 Keen Glidemaster
3151 Kira, Great Glass-Spinner
3161 Mistral Singer
3171 Roaming Ghostlight
3181 Tide Skimmer
3191 Wall of Runes
3201 Windstorm Drake
3211 Lofty Denial
3221 Rain of Revelation
3231 Rookie Mistake
3241 Unsubstantiate
3251 Capture Sphere
3261 Thriving Isle
3277 Island]]},{name="Angels 1", text=[[
3281 Angelic Page
3291 Anointed Chorister
3301 Celestial Enforcer
3311 Baneslayer Angel
3321 Emancipation Angel
3331 Serra Angel
3341 Voice of the Provinces
3351 Angelic Ascension
3361 Feat of Resistance
3371 Angelic Edict
3381 Guardian Idol
3391 Scroll of Avacyn
3401 Thriving Heath
3417 Plains]]},{name="Angels 2", text=[[
3421 Angelic Arbiter
3431 Angelic Page
3441 Anointed Chorister
3451 Celestial Enforcer
3461 Emancipation Angel
3471 Linvala, Keeper of Silence
3481 Serra Angel
3491 Angelic Ascension
3501 Take Heart
3511 Angelic Edict
3521 Guardian Idol
3531 Scroll of Avacyn
3541 Thriving Heath
3557 Plains]]},{name="Archaeology 1", text=[[
3561 Ancestral Statue
3572 Archaeomender
3581 Erratic Visionary
3591 Juggernaut
3601 Lightning-Core Excavator
3611 Meteor Golem
3621 Scholar of the Lost Trove
3631 Thirst for Knowledge
3641 Aether Spellbomb
3651 Chromatic Sphere
3661 Hedron Archive
3671 Buried Ruin
3681 Thriving Isle
3696 Island]]},{name="Archaeology 2", text=[[
3701 Ancestral Statue
3712 Archaeomender
3721 Erratic Visionary
3731 Juggernaut
3741 Lightning-Core Excavator
3751 Meteor Golem
3761 Scholar of the Lost Trove
3771 Thirst for Knowledge
3781 Aether Spellbomb
3791 Dreamstone Hedron
3801 Terrarion
3811 Buried Ruin
3821 Thriving Isle
3836 Island]]},{name="Archaeology 3", text=[[
3841 Ancestral Statue
3852 Archaeomender
3861 Juggernaut
3871 Lightning-Core Excavator
3881 Meteor Golem
3891 Prismite
3901 Sharding Sphinx
3911 Vedalken Archmage
3921 Thirst for Knowledge
3931 Aether Spellbomb
3941 Hedron Archive
3951 Buried Ruin
3961 Thriving Isle
3976 Island]]},{name="Archaeology 4", text=[[
3982 Archaeomender
3991 Jousting Dummy
4001 Juggernaut
4011 Lightning-Core Excavator
4021 Meteor Golem
4031 Scarecrone
4041 Scuttlemutt
4051 Signpost Scarecrow
4061 Thirst for Knowledge
4071 Aether Spellbomb
4081 Short Sword
4091 Buried Ruin
4101 Thriving Isle
4116 Island]]},{name="Basri", text=[[
4121 Basri's Acolyte
4131 Basri's Lieutenant
4141 Concordia Pegasus
4151 Knight of the Tusk
4161 Siege Striker
4171 Staunch Shieldmate
4181 Tempered Veteran
4191 Basri Ket
4201 Feat of Resistance
4211 Basri's Solidarity
4221 Legion's Judgment
4231 Faith's Fetters
4241 Thriving Heath
4257 Plains]]},{name="Cats 1", text=[[
4261 Canopy Stalker
4271 Feline Sovereign
4281 Feral Prowler
4291 Initiate's Companion
4301 Keeper of Fables
4311 Pouncing Cheetah
4321 Pridemalkin
4331 Sabertooth Mauler
4341 Crushing Canopy
4351 Enlarge
4361 Nature's Way
4371 Feral Invocation
4381 Thriving Grove
4397 Forest]]},{name="Cats 2", text=[[
4401 Canopy Stalker
4411 Feline Sovereign
4421 Feral Prowler
4431 Initiate's Companion
4441 Keeper of Fables
4451 Penumbra Bobcat
4461 Pridemalkin
4471 Crushing Canopy
4481 Enlarge
4491 Nature's Way
4501 Feral Invocation
4511 Lurking Predators
4521 Thriving Grove
4537 Forest]]},{name="Chandra", text=[[
4541 Chandra's Incinerator
4552 Chandra's Magmutt
4561 Chandra's Pyreling
4571 Fanatical Firebrand
4581 Pyroclastic Elemental
4591 Young Pyromancer
4601 Chandra, Heart of Fire
4611 Hungry Flames
4621 Thrill of Possibility
4631 Flames of the Firebrand
4641 Pillar of Flame
4651 Thriving Bluff
4667 Mountain]]},{name="Devilish 1", text=[[
4671 Chained Brute
4681 Forge Devil
4691 Havoc Jester
4701 Hobblefiend
4711 Pitchburn Devils
4721 Spiteful Prankster
4731 Torch Fiend
4741 Zurzoth, Chaos Rider
4751 Collateral Damage
4761 Dance with Devils
4771 Heartfire
4781 Traitorous Greed
4791 Thriving Bluff
4807 Mountain]]},{name="Devilish 2", text=[[
4811 Chained Brute
4821 Havoc Jester
4831 Hobblefiend
4841 Pitchburn Devils
4851 Spiteful Prankster
4861 Tibalt's Rager
4872 Torch Fiend
4881 Zurzoth, Chaos Rider
4891 Collateral Damage
4901 Heartfire
4911 Traitorous Greed
4921 Thriving Bluff
4937 Mountain]]},{name="Devilish 3", text=[[
4941 Brash Taunter
4951 Chained Brute
4961 Havoc Jester
4971 Hobblefiend
4981 Lightning-Core Excavator
4991 Pitchburn Devils
5001 Spiteful Prankster
5011 Torch Fiend
5021 Collateral Damage
5031 Dance with Devils
5041 Act of Treason
5051 Traitorous Greed
5061 Thriving Bluff
5077 Mountain]]},{name="Devilish 4", text=[[
5081 Chained Brute
5091 Havoc Jester
5101 Hellrider
5111 Hobblefiend
5121 Lightning-Core Excavator
5131 Pitchburn Devils
5141 Sin Prodder
5151 Spiteful Prankster
5161 Collateral Damage
5171 Act of Treason
5181 Traitorous Greed
5191 Barrage of Expendables
5201 Thriving Bluff
5217 Mountain]]},{name="Dinosaurs 1", text=[[
5221 Colossal Dreadmaw
5231 Drover of the Mighty
5241 Drowsing Tyrannodon
5251 Ghalta, Primal Hunger
5261 Orazca Frillback
5271 Ornery Dilophosaur
5281 Thrashing Brontodon
5291 Crushing Canopy
5301 Commune with Dinosaurs
5311 Cultivate
5321 Savage Stomp
5331 Setessan Training
5341 Thriving Grove
5357 Forest]]},{name="Dinosaurs 2", text=[[
5361 Colossal Dreadmaw
5371 Drover of the Mighty
5381 Drowsing Tyrannodon
5391 Ghalta, Primal Hunger
5401 Orazca Frillback
5411 Ornery Dilophosaur
5421 Thundering Spineback
5431 Crushing Canopy
5441 Titanic Growth
5451 Commune with Dinosaurs
5461 Cultivate
5471 Savage Stomp
5481 Thriving Grove
5497 Forest]]},{name="Dinosaurs 3", text=[[
5501 Colossal Dreadmaw
5511 Drover of the Mighty
5521 Drowsing Tyrannodon
5531 Orazca Frillback
5541 Ornery Dilophosaur
5551 Selvala, Heart of the Wilds
5561 Thundering Spineback
5571 Crushing Canopy
5581 Commune with Dinosaurs
5591 Savage Stomp
5601 Garruk's Uprising
5611 New Horizons
5621 Thriving Grove
5637 Forest]]},{name="Dinosaurs 4", text=[[
5641 Colossal Dreadmaw
5651 Drover of the Mighty
5661 Drowsing Tyrannodon
5671 Orazca Frillback
5681 Ornery Dilophosaur
5691 Rampaging Brontodon
5701 Thrashing Brontodon
5711 Commune with Dinosaurs
5721 Primal Might
5731 Savage Stomp
5741 Garruk's Uprising
5751 New Horizons
5761 Thriving Grove
5777 Forest]]},{name="Discarding 1", text=[[
5781 Burglar Rat
5791 Entomber Exarch
5801 Fell Specter
5811 Phyrexian Rager
5821 Ravenous Chupacabra
5831 Slate Street Ruffian
5841 Tinybones, Trinket Thief
5852 Wight of Precinct Six
5861 Assassin's Strike
5871 Mind Rot
5881 Death's Approach
5891 Thriving Moor
5907 Swamp]]},{name="Discarding 2", text=[[
5911 Burglar Rat
5921 Entomber Exarch
5931 Fell Specter
5941 Liliana's Reaver
5951 Nyxathid
5961 Phyrexian Rager
5971 Ravenous Chupacabra
5981 Slate Street Ruffian
5992 Wight of Precinct Six
6001 Assassin's Strike
6011 Death's Approach
6021 Thriving Moor
6037 Swamp]]},{name="Doctor 1", text=[[
6041 Anointed Chorister
6051 Basri's Acolyte
6061 Brightmare
6071 Bulwark Giant
6081 Mesa Unicorn
6091 Speaker of the Heavens
6101 Revitalize
6111 Swift Response
6121 Take Heart
6131 Faith's Fetters
6141 Griffin Aerie
6151 Light of Promise
6161 Thriving Heath
6177 Plains]]},{name="Doctor 2", text=[[
6181 Angel of Mercy
6191 Anointed Chorister
6201 Basri's Acolyte
6211 Brightmare
6221 Speaker of the Heavens
6231 Stone Haven Pilgrim
6241 Moment of Heroism
6251 Revitalize
6261 Swift Response
6271 Secure the Scene
6281 Griffin Aerie
6291 Light of Promise
6301 Thriving Heath
6317 Plains]]},{name="Doctor 3", text=[[
6321 Angel of Mercy
6331 Anointed Chorister
6341 Basri's Acolyte
6351 Brightmare
6361 Mesa Unicorn
6371 Rhox Faithmender
6381 Moment of Heroism
6391 Revitalize
6401 Swift Response
6411 Faith's Fetters
6421 Griffin Aerie
6431 Light of Promise
6441 Thriving Heath
6457 Plains]]},{name="Doctor 4", text=[[
6461 Alabaster Mage
6471 Angel of Mercy
6481 Anointed Chorister
6491 Basri's Acolyte
6501 Brightmare
6511 Bulwark Giant
6521 Stone Haven Pilgrim
6531 Revitalize
6541 Swift Response
6551 Cradle of Vitality
6561 Griffin Aerie
6571 Path of Bravery
6581 Thriving Heath
6597 Plains]]},{name="Dogs 1", text=[[
6601 Affa Guard Hound
6611 Alpine Watchdog
6621 Cathar's Companion
6631 Pack Leader
6641 Rambunctious Mutt
6651 Selfless Savior
6661 Supply Runners
6671 Trusty Retriever
6681 Feat of Resistance
6691 Release the Dogs
6701 Secure the Scene
6711 Pacifism
6721 Thriving Heath
6737 Plains]]},{name="Dogs 2", text=[[
6741 Affa Guard Hound
6751 Alpine Watchdog
6761 Cathar's Companion
6771 Isamaru, Hound of Konda
6781 Pack Leader
6791 Rambunctious Mutt
6801 Supply Runners
6811 Trusty Retriever
6821 Dauntless Onslaught
6831 Release the Dogs
6841 Secure the Scene
6851 Pacifism
6861 Thriving Heath
6877 Plains]]},{name="Dragons 1", text=[[
6881 Dragonloft Idol
6891 Dragonspeaker Shaman
6901 Dragon Hatchling
6911 Hellkite Punisher
6921 Lightning Shrieker
6931 Rapacious Dragon
6941 Terror of the Peaks
6951 Draconic Roar
6961 Thrill of Possibility
6971 Bathe in Dragonfire
6981 Dragon Fodder
6991 Thriving Bluff
7008 Mountain]]},{name="Dragons 2", text=[[
7011 Dragonlord's Servant
7021 Dragon Hatchling
7031 Furnace Whelp
7041 Gadrak, the Crown-Scourge
7051 Hellkite Punisher
7061 Lathliss, Dragon Queen
7071 Lightning Shrieker
7081 Rapacious Dragon
7091 Draconic Roar
7101 Sarkhan's Rage
7111 Dragon Fodder
7121 Thriving Bluff
7138 Mountain]]},{name="Elves 1", text=[[
7141 Craterhoof Behemoth
7151 Elvish Archdruid
7161 Dwynen's Elite
7171 Ghirapur Guide
7181 Llanowar Visionary
7191 Silhana Wayfinder
7201 Skyway Sniper
7211 Wildheart Invoker
7221 Crushing Canopy
7231 Titanic Growth
7241 Hunter's Edge
7251 Presence of Gond
7261 Thriving Grove
7277 Forest]]},{name="Elves 2", text=[[
7281 Allosaurus Shepherd
7291 Dwynen's Elite
7301 Leaf Gilder
7311 Llanowar Visionary
7321 Silhana Wayfinder
7331 Skyway Sniper
7341 Wildheart Invoker
7351 Wren's Run Vanquisher
7361 Crushing Canopy
7371 Titanic Growth
7381 Hunter's Edge
7391 Presence of Gond
7401 Thriving Grove
7417 Forest]]},{name="Enchanted 1", text=[[
7421 Anointed Chorister
7431 Blessed Spirits
7441 Knight of the Tusk
7451 Kor Spiritdancer
7461 Stone Haven Pilgrim
7471 Trusty Retriever
7481 Dub
7491 Face of Divinity
7501 Faith's Fetters
7511 Forced Worship
7521 Indomitable Will
7531 Knightly Valor
7541 Thriving Heath
7557 Plains]]},{name="Enchanted 2", text=[[
7561 Ajani's Chosen
7571 Blessed Spirits
7581 Bulwark Giant
7591 Staunch Shieldmate
7601 Stone Haven Pilgrim
7611 Trusty Retriever
7621 Celestial Mantle
7631 Face of Divinity
7641 Faith's Fetters
7651 Forced Worship
7661 Indomitable Will
7671 Knightly Valor
7681 Thriving Heath
7697 Plains]]},{name="Feathered Friends 1", text=[[
7701 Aven Gagglemaster
7711 Celestial Enforcer
7721 Concordia Pegasus
7731 Falconer Adept
7741 Gale Swooper
7751 Healer's Hawk
7761 Steel-Plume Marshal
7771 Warded Battlements
7781 Dauntless Onslaught
7791 Moment of Heroism
7801 Aerial Assault
7811 Sky Tether
7821 Thriving Heath
7837 Plains]]},{name="Feathered Friends 2", text=[[
7841 Aven Gagglemaster
7851 Celestial Enforcer
7861 Concordia Pegasus
7871 Falconer Adept
7881 Gale Swooper
7891 Healer's Hawk
7901 Steel-Plume Marshal
7911 Warded Battlements
7921 Angelic Ascension
7931 Swift Response
7941 Tandem Tactics
7951 Sky Tether
7961 Thriving Heath
7977 Plains]]},{name="Feathered Friends 3", text=[[
7981 Angel of the Dire Hour
7991 Aven Gagglemaster
8001 Celestial Enforcer
8011 Concordia Pegasus
8021 Falconer Adept
8031 Gale Swooper
8041 Healer's Hawk
8051 Warded Battlements
8061 Dauntless Onslaught
8071 Swift Response
8081 Take Heart
8091 Sky Tether
8101 Thriving Heath
8117 Plains]]},{name="Feathered Friends 4", text=[[
8121 Archon of Justice
8131 Archon of Redemption
8141 Celestial Enforcer
8151 Concordia Pegasus
8161 Falconer Adept
8171 Gale Swooper
8181 Healer's Hawk
8191 Warded Battlements
8201 Aegis of the Heavens
8211 Dauntless Onslaught
8221 Aerial Assault
8231 Sky Tether
8241 Thriving Heath
8257 Plains]]},{name="Garruk", text=[[
8261 Affectionate Indrik
8271 Brushstrider
8281 Drowsing Tyrannodon
8291 Garruk's Gorehorn
8301 Garruk's Harbinger
8311 Orazca Frillback
8321 Rumbling Baloth
8331 Garruk, Unleashed
8341 Hunter's Insight
8351 Ranger's Guile
8361 Hunter's Edge
8371 Garruk's Uprising
8381 Thriving Grove
8397 Forest]]},{name="Goblins 1", text=[[
8401 Beetleback Chief
8411 Boggart Brute
8421 Goblin Arsonist
8431 Goblin Commando
8441 Goblin Instigator
8451 Goblin Shortcutter
8461 Muxus, Goblin Grandee
8471 Ornery Goblin
8481 Volley Veteran
8491 Outnumber
8501 Shock
8511 Makeshift Munitions
8521 Thriving Bluff
8537 Mountain]]},{name="Goblins 2", text=[[
8541 Battle-Rattle Shaman
8551 Beetleback Chief
8561 Boggart Brute
8571 Goblin Arsonist
8581 Goblin Commando
8591 Goblin Instigator
8601 Goblin Shortcutter
8611 Muxus, Goblin Grandee
8621 Ornery Goblin
8631 Burn Bright
8641 Outnumber
8651 Makeshift Munitions
8661 Thriving Bluff
8677 Mountain]]},{name="Goblins 3", text=[[
8681 Beetleback Chief
8691 Boggart Brute
8701 Goblin Arsonist
8711 Goblin Chieftain
8721 Goblin Commando
8731 Goblin Goon
8741 Goblin Instigator
8751 Goblin Shortcutter
8761 Ornery Goblin
8771 Volley Veteran
8781 Shock
8791 Makeshift Munitions
8801 Thriving Bluff
8817 Mountain]]},{name="Goblins 4", text=[[
8821 Boggart Brute
8831 Goblin Arsonist
8841 Goblin Commando
8851 Goblin Instigator
8861 Goblin Shortcutter
8871 Krenko, Mob Boss
8881 Ornery Goblin
8891 Burn Bright
8901 Outnumber
8911 Goblin Lore
8921 Goblin Rally
8931 Makeshift Munitions
8941 Thriving Bluff
8957 Mountain]]},{name="Heavily Armored 1", text=[[
8961 Basri's Acolyte
8971 Bulwark Giant
8981 Lightwalker
8991 Makeshift Battalion
9001 Patron of the Valiant
9011 Siege Striker
9021 Tempered Veteran
9031 Trusty Retriever
9041 Feat of Resistance
9051 Basri's Solidarity
9061 Secure the Scene
9071 Cathars' Crusade
9081 Thriving Heath
9097 Plains]]},{name="Heavily Armored 2", text=[[
9101 Basri's Acolyte
9111 Bulwark Giant
9121 Lightwalker
9131 Makeshift Battalion
9141 Patron of the Valiant
9151 Siege Striker
9161 Tempered Veteran
9171 Trusty Retriever
9181 Battlefield Promotion
9191 Gird for Battle
9201 Secure the Scene
9211 Cathars' Crusade
9221 Thriving Heath
9237 Plains]]},{name="Heavily Armored 3", text=[[
9241 Basri's Acolyte
9251 Bulwark Giant
9261 Lightwalker
9271 Makeshift Battalion
9281 Mikaeus, the Lunarch
9291 Patron of the Valiant
9301 Supply Runners
9311 Tempered Veteran
9321 Trusty Retriever
9331 Battlefield Promotion
9341 Divine Arrow
9351 Basri's Solidarity
9361 Thriving Heath
9377 Plains]]},{name="Heavily Armored 4", text=[[
9381 Basri's Acolyte
9391 Bulwark Giant
9401 Lightwalker
9411 High Sentinels of Arashin
9421 Makeshift Battalion
9431 Siege Striker
9441 Supply Runners
9451 Tempered Veteran
9461 Trusty Retriever
9471 Long Road Home
9481 Swift Response
9491 Duelist's Heritage
9501 Thriving Heath
9517 Plains]]},{name="Lands 1", text=[[
9521 Awakener Druid
9531 Fa'adiyah Seer
9541 Feral Hydra
9551 Fertilid
9561 Sylvan Ranger
9571 Ulvenwald Hydra
9581 Wildheart Invoker
9591 Crushing Canopy
9601 Elemental Uprising
9611 Cultivate
9621 Vastwood Zendikon
9631 Zendikar's Roil
9641 Thriving Grove
9657 Forest]]},{name="Lands 2", text=[[
9661 Awakener Druid
9671 Fa'adiyah Seer
9681 Feral Hydra
9691 Fertilid
9701 Oracle of Mul Daya
9711 Sporemound
9721 Sylvan Ranger
9731 Wildheart Invoker
9741 Woodborn Behemoth
9751 Crushing Canopy
9761 Elemental Uprising
9771 Cultivate
9781 Thriving Grove
9797 Forest]]},{name="Legion 1", text=[[
9801 Daybreak Charger
9811 Falconer Adept
9821 Knight of the Tusk
9831 Makeshift Battalion
9841 Selfless Savior
9851 Valorous Steed
9861 Inspired Charge
9871 Path to Exile
9881 Raise the Alarm
9891 Basri's Solidarity
9901 Legion's Judgment
9911 Blessed Sanctuary
9921 Thriving Heath
9937 Plains]]},{name="Legion 2", text=[[
9941 Daybreak Charger
9951 Inspiring Captain
9961 Makeshift Battalion
9971 Siege Striker
9981 Staunch Shieldmate
9991 Valorous Steed
10001 Raise the Alarm
10011 Basri's Solidarity
10021 Legion's Judgment
10031 Release the Dogs
10041 Glorious Anthem
10051 Faith's Fetters
10061 Thriving Heath
10077 Plains]]},{name="Legion 3", text=[[
10081 Daybreak Charger
10091 Makeshift Battalion
10101 Siege Striker
10111 Staunch Shieldmate
10121 Valorous Steed
10131 Raise the Alarm
10141 Fortify
10151 Basri's Solidarity
10161 Legion's Judgment
10171 Release the Dogs
10181 Glorious Anthem
10191 Faith's Fetters
10201 Thriving Heath
10217 Plains]]},{name="Legion 4", text=[[
10221 Daybreak Charger
10231 Lena, Selfless Champion
10241 Makeshift Battalion
10251 Mentor of the Meek
10261 Selfless Savior
10271 Siege Striker
10281 Valorous Steed
10291 Raise the Alarm
10301 Fortify
10311 Basri's Solidarity
10321 Legion's Judgment
10331 Faith's Fetters
10341 Thriving Heath
10357 Plains]]},{name="Lightning 1", text=[[
10361 Lightning Elemental
10371 Lightning Phoenix
10381 Lightning Shrieker
10392 Lightning Visionary
10401 Lightning-Core Excavator
10411 Living Lightning
10421 Weaver of Lightning
10431 Homing Lightning
10441 Lightning Axe
10451 Lightning Bolt
10461 Lightning Diadem
10471 Thriving Bluff
10487 Mountain]]},{name="Lightning 2", text=[[
10491 Ball Lightning
10501 Lightning Elemental
10511 Lightning Phoenix
10522 Lightning Visionary
10531 Lightning-Core Excavator
10541 Living Lightning
10551 Weaver of Lightning
10561 Chain Lightning
10571 Lightning Axe
10581 Riddle of Lightning
10591 Lightning Diadem
10601 Thriving Bluff
10617 Mountain]]},{name="Liliana", text=[[
10621 Blighted Bat
10631 Ghoulraiser
10641 Goremand
10651 Liliana's Devotee
10661 Liliana's Elite
10671 Liliana's Standard Bearer
10681 Liliana's Steward
10691 Wailing Ghoul
10701 Liliana, Waker of the Dead
10711 Cemetery Recruitment
10721 Rise Again
10731 Settle the Score
10741 Thriving Moor
10757 Swamp]]},{name="Mill", text=[[
10761 Belltower Sphinx
10771 Bruvac the Grandiloquent
10781 Reckless Scholar
10791 Selhoff Occultist
10801 Towering-Wave Mystic
10811 Vedalken Entrancer
10821 Wall of Lost Thoughts
10831 Sweep Away
10841 Thought Collapse
10851 Thought Scour
10861 Capture Sphere
10871 Teferi's Tutelage
10881 Thriving Isle
10897 Island]]},{name="Minions 1", text=[[
10901 Bone Picker
10911 Crypt Lurker
10921 Dutiful Attendant
10931 Ghoulcaller's Accomplice
10941 Goremand
10951 Kels, Fight Fixer
10961 Nocturnal Feeder
10971 Shambling Goblin
10981 Eliminate
10991 Village Rites
11001 Innocent Blood
11011 Witch's Cauldron
11021 Thriving Moor
11037 Swamp]]},{name="Minions 2", text=[[
11041 Crypt Lurker
11051 Drainpipe Vermin
11061 Dutiful Attendant
11071 Eternal Taskmaster
11081 Ghoulcaller's Accomplice
11091 Goremand
11101 Kels, Fight Fixer
11111 Nocturnal Feeder
11121 Eliminate
11131 Village Rites
11141 Bone Splinters
11151 Witch's Cauldron
11161 Thriving Moor
11177 Swamp]]},{name="Minions 3", text=[[
11181 Crypt Lurker
11191 Drainpipe Vermin
11201 Dutiful Attendant
11211 Fetid Imp
11221 Ghoulcaller's Accomplice
11231 Goremand
11241 Liliana's Devotee
11251 Nocturnal Feeder
11261 Eliminate
11271 Launch Party
11281 Village Rites
11291 Witch's Cauldron
11301 Phyrexian Tower
11311 Thriving Moor
11326 Swamp]]},{name="Minions 4", text=[[
11331 Dutiful Attendant
11341 Fetid Imp
11351 Ghoulcaller's Accomplice
11361 Ghoulcaller Gisa
11371 Goremand
11381 Liliana's Devotee
11391 Nocturnal Feeder
11401 Shambling Goblin
11411 Eliminate
11421 Village Rites
11431 Innocent Blood
11441 Witch's Cauldron
11451 Thriving Moor
11467 Swamp]]},{name="Minotaurs 1", text=[[
11471 Bloodrage Brawler
11481 Borderland Minotaur
11491 Lightning Visionary
11501 Minotaur Skullcleaver
11511 Minotaur Sureshot
11521 Sethron, Hurloon General
11531 Warfire Javelineer
11541 Soul Sear
11551 Sure Strike
11561 Flurry of Horns
11571 Mugging
11581 Herald's Horn
11591 Thriving Bluff
11607 Mountain]]},{name="Minotaurs 2", text=[[
11611 Bloodrage Brawler
11621 Borderland Minotaur
11631 Lightning Visionary
11641 Minotaur Skullcleaver
11651 Minotaur Sureshot
11661 Rageblood Shaman
11671 Sethron, Hurloon General
11681 Soul Sear
11691 Sure Strike
11701 Unleash Fury
11711 Flurry of Horns
11721 Traitorous Greed
11731 Thriving Bluff
11747 Mountain]]},{name="Phyrexian", text=[[
11751 Entomber Exarch
11761 Myr Sire
11771 Perilous Myr
11781 Phyrexian Broodlings
11791 Phyrexian Gargantua
11801 Phyrexian Debaser
11811 Phyrexian Rager
11821 Sheoldred, Whispering One
11831 Douse in Gloom
11841 Parasitic Implant
11851 Phyrexian Reclamation
11861 Malefic Scythe
11871 Thriving Moor
11887 Swamp]]},{name="Pirates 1", text=[[
11891 Corsair Captain
11901 Departed Deckhand
11911 Kitesail Corsair
11921 Prosperous Pirates
11931 Rishadan Airship
11941 Sailor of Means
11951 Spectral Sailor
11961 Voyage's End
11971 Chart a Course
11981 Coastal Piracy
11991 Waterknot
12001 Pirate's Cutlass
12011 Thriving Isle
12027 Island]]},{name="Pirates 2", text=[[
12031 Corsair Captain
12041 Departed Deckhand
12051 Kitesail Corsair
12061 Prosperous Pirates
12071 Rishadan Airship
12081 Sailor of Means
12091 Spectral Sailor
12101 Chart a Course
12111 Read the Tides
12121 Capture Sphere
12131 Curious Obsession
12141 Pirate's Cutlass
12151 Thriving Isle
12167 Island]]},{name="Plus One 1", text=[[
12171 Armorcraft Judge
12181 Fertilid
12191 Ironshell Beetle
12201 Nessian Hornbeetle
12211 Pridemalkin
12221 Trufflesnout
12231 Wildwood Scourge
12241 Arbor Armament
12251 Invigorating Surge
12261 Hunter's Edge
12271 Primeval Bounty
12281 Thriving Grove
12298 Forest]]},{name="Plus One 2", text=[[
12301 Armorcraft Judge
12311 Fertilid
12321 Ironshell Beetle
12331 Nessian Hornbeetle
12341 Pridemalkin
12351 Trufflesnout
12361 Wildwood Scourge
12371 Arbor Armament
12381 Invigorating Surge
12391 Hunter's Edge
12401 Branching Evolution
12411 Thriving Grove
12428 Forest]]},{name="Plus One 3", text=[[
12431 Fertilid
12441 Nessian Hornbeetle
12451 Pridemalkin
12461 Rishkar, Peema Renegade
12471 Scrounging Bandar
12481 Trufflesnout
12491 Wildwood Scourge
12501 Arbor Armament
12511 Inspiring Call
12521 Invigorating Surge
12531 Hunter's Edge
12541 Thriving Grove
12558 Forest]]},{name="Plus One 4", text=[[
12561 Champion of Lambholt
12571 Nessian Hornbeetle
12581 Pridemalkin
12591 Scrounging Bandar
12601 Trufflesnout
12611 Wildwood Scourge
12621 Arbor Armament
12631 Invigorating Surge
12641 Lifecrafter's Gift
12651 Hunter's Edge
12661 Branching Evolution
12671 Thriving Grove
12688 Forest]]},{name="Predatory 1", text=[[
12691 Brindle Shoat
12701 Dawntreader Elk
12711 Neyith of the Dire Hunt
12721 Sabertooth Mauler
12731 Somberwald Stag
12741 Sylvan Brushstrider
12751 Trufflesnout
12761 Crushing Canopy
12771 Fungal Rebirth
12781 Irresistible Prey
12791 Time to Feed
12801 Marauder’s Axe
12811 Thriving Grove
12827 Forest]]},{name="Predatory 2", text=[[
12831 Affectionate Indrik
12841 Brindle Shoat
12851 Dawntreader Elk
12861 Gingerbrute
12871 Neyith of the Dire Hunt
12881 Sabertooth Mauler
12891 Trufflesnout
12901 Crushing Canopy
12911 Fungal Rebirth
12921 Irresistible Prey
12931 Time to Feed
12941 Marauder’s Axe
12951 Thriving Grove
12967 Forest]]},{name="Predatory 3", text=[[
12971 Brindle Shoat
12981 Dawntreader Elk
12991 Gingerbrute
13001 Sabertooth Mauler
13011 Somberwald Stag
13021 Thragtusk
13031 Trufflesnout
13041 Crushing Canopy
13051 Fungal Rebirth
13061 Irresistible Prey
13071 Time to Feed
13081 Marauder’s Axe
13091 Thriving Grove
13107 Forest]]},{name="Predatory 4", text=[[
13111 Affectionate Indrik
13121 Brindle Shoat
13131 Dawntreader Elk
13141 Ravenous Baloth
13151 Sabertooth Mauler
13161 Sylvan Brushstrider
13171 Trufflesnout
13181 Crushing Canopy
13191 Momentous Fall
13201 Fungal Rebirth
13211 Irresistible Prey
13221 Time to Feed
13231 Thriving Grove
13247 Forest]]},{name="Rainbow", text=[[
13251 Alloy Myr
13261 Chamber Sentry
13271 Dinrova Horror
13281 Fusion Elemental
13291 Ironroot Warlord
13301 Maelstrom Archangel
13311 Prismite
13321 Raging Regisaur
13331 Skittering Surveyor
13341 Auger Spree
13351 Lawmage's Binding
13361 Prophetic Prism
13371 Mirrodin's Core
13381 Rupture Spire
13391 Terramorphic Expanse
13401 Plains
13411 Island
13421 Swamp
13431 Mountain
13441 Forest]]},{name="Reanimated 1", text=[[
13451 Archfiend's Vessel
13461 Cadaver Imp
13471 Crow of Dark Tidings
13481 Crypt Lurker
13491 Goremand
13501 Miasmic Mummy
13511 Mire Triton
13521 Tithebearer Giant
13531 Eliminate
13541 Funeral Rites
13551 Reanimate
13561 Rise Again
13571 Thriving Moor
13587 Swamp]]},{name="Reanimated 2", text=[[
13591 Carrion Grub
13601 Crow of Dark Tidings
13611 Crypt Lurker
13621 Gloom Sower
13631 Goremand
13641 Miasmic Mummy
13651 Mire Triton
13661 Eliminate
13671 Funeral Rites
13681 Macabre Waltz
13691 Reanimate
13701 Rise Again
13711 Thriving Moor
13727 Swamp]]},{name="Reanimated 3", text=[[
13731 Crow of Dark Tidings
13741 Crypt Lurker
13751 Goremand
13761 Gravewaker
13771 Miasmic Mummy
13781 Mire Triton
13791 Scourge of Nel Toth
13801 Eliminate
13811 Exhume
13821 Funeral Rites
13831 Rise Again
13841 Zombie Infestation
13851 Thriving Moor
13867 Swamp]]},{name="Reanimated 4", text=[[
13871 Carrion Grub
13881 Crow of Dark Tidings
13891 Crypt Lurker
13901 Goremand
13911 Gloom Sower
13921 Miasmic Mummy
13931 Mire Triton
13941 Eliminate
13951 Funeral Rites
13961 Rise Again
13971 Rise of the Dark Realms
13981 Soul Salvage
13991 Thriving Moor
14007 Swamp]]},{name="Rogues 1", text=[[
14011 Gonti, Lord of Luxury
14021 Lawless Broker
14031 Mausoleum Turnkey
14041 Masked Blackguard
14051 Nightshade Stinger
14061 Nocturnal Feeder
14071 Oona's Blackguard
14081 Thieves' Guild Enforcer
14091 Alchemist's Gift
14101 Finishing Blow
14111 Stab Wound
14121 Rogue's Gloves
14131 Thriving Moor
14147 Swamp]]},{name="Rogues 2", text=[[
14151 Corpse Hauler
14161 Corpse Traders
14171 Lawless Broker
14181 Masked Blackguard
14191 Nightshade Stinger
14201 Nocturnal Feeder
14211 Oona's Blackguard
14221 Thieves' Guild Enforcer
14231 Alchemist's Gift
14241 Last Gasp
14251 Stab Wound
14261 Rogue's Gloves
14271 Thriving Moor
14287 Swamp]]},{name="Seismic", text=[[
14291 Ashmouth Hound
14301 Bloodrock Cyclops
14311 Cinder Elemental
14321 Grim Lavamancer
14331 Seismic Elemental
14341 Molten Ravager
14351 Magma Jet
14361 Magmaquake
14371 Volcanic Fallout
14381 Volcanic Geyser
14391 Spitting Earth
14401 Mana Geode
14411 Thriving Bluff
14427 Mountain]]},{name="Smashing 1", text=[[
14431 Bloodrage Brawler
14441 Bone Pit Brute
14451 Borderland Marauder
14461 Flametongue Kavu
14471 Heartfire Immolator
14481 Onakke Ogre
14491 Turret Ogre
14501 Fling
14511 Shock
14521 Unleash Fury
14531 Volcanic Salvo
14541 Furious Rise
14551 Thriving Bluff
14567 Mountain]]},{name="Smashing 2", text=[[
14571 Bloodrage Brawler
14581 Bone Pit Brute
14591 Borderland Marauder
14601 Heartfire Immolator
14611 Onakke Ogre
14621 Turret Ogre
14631 Flames of the Raze-Boar
14641 Fling
14651 Hungry Flames
14661 Volcanic Salvo
14671 Furious Rise
14681 Short Sword
14691 Thriving Bluff
14707 Mountain]]},{name="Smashing 3", text=[[
14711 Bloodrage Brawler
14721 Bone Pit Brute
14731 Borderland Marauder
14741 Hamletback Goliath
14751 Heartfire Immolator
14761 Inferno Hellion
14771 Onakke Ogre
14781 Turret Ogre
14791 Fling
14801 Unleash Fury
14811 Furious Rise
14821 Sarkhan's Unsealing
14831 Thriving Bluff
14847 Mountain]]},{name="Smashing 4", text=[[
14851 Bloodrage Brawler
14861 Bloodshot Trainee
14871 Bone Pit Brute
14881 Borderland Marauder
14891 Etali, Primal Storm
14901 Heartfire Immolator
14911 Onakke Ogre
14921 Turret Ogre
14931 Fling
14941 Hungry Flames
14951 Furious Rise
14961 Furor of the Bitten
14971 Thriving Bluff
14987 Mountain]]},{name="Spellcasting 1", text=[[
14991 Chandra's Pyreling
15001 Heartfire Immolator
15011 Kinetic Augur
15021 Lightning Visionary
15031 Living Lightning
15041 Thermo-Alchemist
15051 Blindblast
15061 Hungry Flames
15071 Shock
15081 Thrill of Possibility
15091 Goblin Wizardry
15101 Double Vision
15111 Thriving Bluff
15127 Mountain]]},{name="Spellcasting 2", text=[[
15131 Chandra's Pyreling
15141 Heartfire Immolator
15151 Kiln Fiend
15161 Kinetic Augur
15171 Lightning Visionary
15181 Thermo-Alchemist
15191 Young Pyromancer
15201 Flame Lash
15211 Hungry Flames
15221 Shock
15231 Thrill of Possibility
15241 Double Vision
15251 Thriving Bluff
15267 Mountain]]},{name="Spellcasting 3", text=[[
15271 Chandra's Pyreling
15281 Charmbreaker Devils
15291 Dualcaster Mage
15301 Heartfire Immolator
15311 Kinetic Augur
15321 Lightning Visionary
15331 Living Lightning
15341 Thermo-Alchemist
15351 Hungry Flames
15361 Shock
15371 Thrill of Possibility
15381 Dragon Fodder
15391 Thriving Bluff
15407 Mountain]]},{name="Spellcasting 4", text=[[
15411 Chandra's Pyreling
15421 Heartfire Immolator
15431 Kiln Fiend
15441 Kinetic Augur
15451 Lightning Visionary
15461 Thermo-Alchemist
15471 Hungry Flames
15481 Shock
15491 Thrill of Possibility
15501 Crash Through
15511 Doublecast
15521 Immolating Gyre
15531 Thriving Bluff
15547 Mountain]]},{name="Spirits 1", text=[[
15551 Battleground Geist
15561 Departed Deckhand
15571 Murmuring Phantasm
15581 Nebelgast Herald
15591 Roaming Ghostlight
15601 Shacklegeist
15611 Tome Anima
15621 Befuddle
15631 Essence Flux
15641 Frost Breath
15651 Winged Words
15661 Capture Sphere
15671 Thriving Isle
15687 Island]]},{name="Spirits 2", text=[[
15691 Battleground Geist
15701 Departed Deckhand
15711 Nebelgast Herald
15721 Rattlechains
15731 Roaming Ghostlight
15741 Shacklegeist
15751 Tome Anima
15761 Frost Breath
15771 Rewind
15781 Rookie Mistake
15791 Winged Words
15801 Capture Sphere
15811 Thriving Isle
15827 Island]]},{name="Spooky 1", text=[[
15831 Bone Picker
15841 Caged Zombie
15851 Crypt Lurker
15861 Dutiful Attendant
15871 Eternal Taskmaster
15881 Fetid Imp
15891 Gristle Grinner
15901 Liliana's Standard Bearer
15911 Finishing Blow
15921 Village Rites
15931 Barter in Blood
15941 Malefic Scythe
15951 Thriving Moor
15967 Swamp]]},{name="Spooky 2", text=[[
15971 Bone Picker
15981 Caged Zombie
15991 Crypt Lurker
16001 Dutiful Attendant
16011 Eternal Taskmaster
16021 Gristle Grinner
16031 Harvester of Souls
16041 Sanitarium Skeleton
16051 Finishing Blow
16061 Barter in Blood
16071 Bone Splinters
16081 Malefic Scythe
16091 Thriving Moor
16107 Swamp]]},{name="Spooky 3", text=[[
16111 Bone Picker
16121 Caged Zombie
16131 Crypt Lurker
16141 Dutiful Attendant
16151 Eternal Taskmaster
16161 Fetid Imp
16171 Gristle Grinner
16181 Liliana's Devotee
16191 Ogre Slumlord
16201 Finishing Blow
16211 Languish
16221 Malefic Scythe
16231 Thriving Moor
16247 Swamp]]},{name="Spooky 4", text=[[
16251 Bone Picker
16261 Caged Zombie
16271 Crypt Lurker
16281 Dutiful Attendant
16291 Eternal Taskmaster
16301 Gristle Grinner
16311 Liliana's Devotee
16321 Plagued Rusalka
16331 Sanitarium Skeleton
16341 Finishing Blow
16351 Malefic Scythe
16361 Black Market
16371 Thriving Moor
16387 Swamp]]},{name="Teferi", text=[[
16391 Prescient Chimera
16401 Sage's Row Savant
16411 Teferi's Protege
16421 Tolarian Kraken
16431 Vodalian Arcanist
16441 Teferi, Master of Time
16451 Exclude
16461 Leave in the Dust
16471 Opt
16481 Talrand's Invocation
16491 Teferi's Ageless Insight
16501 Teferi's Tutelage
16511 Thriving Isle
16527 Island]]},{name="Tree-Hugging 1", text=[[
16531 Ambassador Oak
16541 Burlfist Oak
16551 Gnarled Sage
16561 Llanowar Visionary
16571 Primordial Sage
16581 Snarespinner
16591 Wall of Blossoms
16601 Warden of the Woods
16611 Aggressive Urge
16621 Crushing Canopy
16631 Explore
16641 Nature's Way
16651 Thriving Grove
16667 Forest]]},{name="Tree-Hugging 2", text=[[
16671 Burlfist Oak
16681 Gnarled Sage
16691 Llanowar Visionary
16701 Primordial Sage
16711 Snarespinner
16721 Wall of Blossoms
16731 Warden of the Woods
16741 Aggressive Urge
16751 Crushing Canopy
16761 Wildsize
16771 Explore
16781 Nature's Way
16791 Thriving Grove
16807 Forest]]},{name="Tree-Hugging 3", text=[[
16811 Ambassador Oak
16821 Burlfist Oak
16831 Gnarled Sage
16841 Jolrael, Mwonvuli Recluse
16851 Llanowar Visionary
16861 Snarespinner
16871 Wall of Blossoms
16881 Warden of the Woods
16891 Aggressive Urge
16901 Crushing Canopy
16911 Explore
16921 Nature's Way
16931 Thriving Grove
16947 Forest]]},{name="Tree-Hugging 4", text=[[
16951 Burlfist Oak
16961 Gnarled Sage
16971 Llanowar Visionary
16981 Snarespinner
16991 Soul of the Harvest
17001 Wall of Blossoms
17011 Warden of the Woods
17021 Crushing Canopy
17031 Wildsize
17041 Explore
17051 Nature's Way
17061 Verdant Embrace
17071 Thriving Grove
17087 Forest]]},{name="Under the Sea 1", text=[[
17091 Aegis Turtle
17101 Octoprophet
17111 Pursued Whale
17121 Sigiled Starfish
17131 Tolarian Kraken
17141 Waker of Waves
17151 Wishful Merfolk
17161 Voyage's End
17171 Rousing Read
17181 Waterknot
17191 Unstable Obelisk
17201 Thriving Isle
17218 Island]]},{name="Under the Sea 2", text=[[
17221 Aegis Turtle
17231 Cryptic Serpent
17241 Octoprophet
17251 Pursued Whale
17261 Sigiled Starfish
17271 Waker of Waves
17281 Wishful Merfolk
17291 Sweep Away
17301 Whelming Wave
17311 Waterknot
17321 Unstable Obelisk
17331 Thriving Isle
17348 Island]]},{name="Unicorns", text=[[
17351 Brightmare
17361 Daybreak Charger
17371 Emiel the Blessed
17381 Inspiring Unicorn
17391 Mesa Unicorn
17401 Ronom Unicorn
17411 Valorous Steed
17421 Cloudshift
17431 Inspired Charge
17441 Valorous Stance
17451 Blessed Sanctuary
17461 Faith's Fetters
17471 Thriving Heath
17487 Plains]]},{name="Vampires 1", text=[[
17491 Blood Artist
17501 Bloodbond Vampire
17511 Gifted Aetherborn
17521 Gloom Sower
17531 Kalastria Nightwatch
17541 Nocturnal Feeder
17551 Silversmote Ghoul
17561 Vito, Thorn of the Dusk Rose
17571 Agonizing Syphon
17581 Sanguine Indulgence
17591 Last Gasp
17601 Eternal Thirst
17611 Thriving Moor
17627 Swamp]]},{name="Vampires 2", text=[[
17631 Blood Host
17641 Bloodbond Vampire
17651 Child of Night
17661 Gifted Aetherborn
17671 Gloom Sower
17681 Nocturnal Feeder
17691 Silversmote Ghoul
17701 Vito, Thorn of the Dusk Rose
17711 Agonizing Syphon
17721 Sanguine Indulgence
17731 Last Gasp
17741 Eternal Thirst
17751 Thriving Moor
17767 Swamp]]},{name="Vampires 3", text=[[
17771 Bloodbond Vampire
17781 Gifted Aetherborn
17791 Gloom Sower
17801 Nocturnal Feeder
17811 Sangromancer
17821 Sengir Vampire
17831 Silversmote Ghoul
17841 Vampire Neonate
17851 Agonizing Syphon
17861 Sanguine Indulgence
17871 Last Gasp
17881 Exquisite Blood
17891 Thriving Moor
17907 Swamp]]},{name="Vampires 4", text=[[
17911 Bloodbond Vampire
17921 Child of Night
17931 Drana, Liberator of Malakir
17941 Falkenrath Noble
17951 Gifted Aetherborn
17961 Gloom Sower
17971 Nocturnal Feeder
17981 Silversmote Ghoul
17991 Agonizing Syphon
18001 Sanguine Indulgence
18011 Last Gasp
18021 Mark of the Vampire
18031 Thriving Moor
18047 Swamp]]},{name="Walls", text=[[
18051 Carven Caryatid
18061 Gargoyle Sentinel
18071 Grave Bramble
18081 Overgrown Battlement
18091 Portcullis Vine
18101 Roving Keep
18111 Towering Titan
18121 Wall of Blossoms
18131 Wall of Vines
18141 Crushing Canopy
18151 Warmonger's Chariot
18161 Assault Formation
18171 Thriving Grove
18187 Forest]]},{name="Well-Read 1", text=[[
18191 Erratic Visionary
18201 Library Larcenist
18211 Oneirophage
18221 Ormos, Archive Keeper
18231 Runed Servitor
18241 Suspicious Bookcase
18251 Tolarian Kraken
18261 Tome Anima
18271 Opt
18281 Curiosity
18291 Narcolepsy
18301 Rousing Read
18311 Thriving Isle
18327 Island]]},{name="Well-Read 2", text=[[
18331 Erratic Visionary
18341 Library Larcenist
18351 Oneirophage
18361 Ormos, Archive Keeper
18371 Runed Servitor
18381 Tolarian Kraken
18391 Tome Anima
18401 Opt
18411 Arcane Encyclopedia
18421 Capture Sphere
18431 Curiosity
18441 Rousing Read
18451 Thriving Isle
18467 Island]]},{name="Well-Read 3", text=[[
18471 Cloudreader Sphinx
18481 Erratic Visionary
18491 Library Larcenist
18501 Oneirophage
18511 Runed Servitor
18521 Suspicious Bookcase
18531 Tolarian Kraken
18541 Tome Anima
18551 Opt
18561 Curiosity
18571 Narcolepsy
18581 Rhystic Study
18591 Thriving Isle
18607 Island]]},{name="Well-Read 4", text=[[
18611 Cloudreader Sphinx
18621 Library Larcenist
18631 Mystic Archaeologist
18641 Oneirophage
18651 Runed Servitor
18661 Suspicious Bookcase
18671 Tolarian Kraken
18681 Tome Anima
18691 Opt
18701 Read the Runes
18711 Capture Sphere
18721 Curiosity
18731 Thriving Isle
18747 Island]]},{name="Witchcraft 1", text=[[
18751 Bloodhunter Bat
18761 Bogbrew Witch
18771 Cauldron Familiar
18782 Festering Newt
18791 Malakir Familiar
18801 Tempting Witch
18811 Witch of the Moors
18821 Bake into a Pie
18831 Finishing Blow
18841 Bubbling Cauldron
18851 Witch's Cauldron
18861 Thriving Moor
18877 Swamp]]},{name="Witchcraft 2", text=[[
18881 Black Cat
18891 Bloodhunter Bat
18901 Bogbrew Witch
18912 Festering Newt
18921 Swarm of Bloodflies
18931 Tempting Witch
18941 Witch of the Moors
18951 Bake into a Pie
18961 Last Gasp
18971 Blood Divination
18981 Bubbling Cauldron
18991 Thriving Moor
19007 Swamp]]},{name="Wizards 1", text=[[
19011 Exclusion Mage
19021 Sage's Row Savant
19031 Shipwreck Dowser
19041 Talrand, Sky Summoner
19051 Vodalian Arcanist
19061 Read the Tides
19071 Talrand's Invocation
19081 Winged Words
19091 Befuddle
19101 Frost Breath
19111 Opt
19121 Wizard's Retort
19131 Thriving Isle
19147 Island]]},{name="Wizards 2", text=[[
19151 Crookclaw Transmuter
19161 Exclusion Mage
19171 Sage's Row Savant
19181 Sea Gate Oracle
19191 Shipwreck Dowser
19201 Vodalian Arcanist
19211 Read the Tides
19221 Talrand's Invocation
19231 Winged Words
19241 Opt
19251 Rookie Mistake
19261 Wizard's Retort
19271 Thriving Isle
19281 Riptide Laboratory
19296 Island]]},{name="Wizards 3", text=[[
19301 Sage's Row Savant
19311 Shipwreck Dowser
19321 Talrand, Sky Summoner
19331 Teferi's Protege
19341 Vodalian Arcanist
19351 Read the Tides
19361 Talrand's Invocation
19371 Winged Words
19381 Opt
19391 Unsubstantiate
19401 Wizard's Retort
19411 Capture Sphere
19421 Thriving Isle
19437 Island ]]},{name="Wizards 4", text=[[
19441 Barrin, Tolarian Archmage
19451 Sage's Row Savant
19461 Shipwreck Dowser
19471 Storm Sculptor
19481 Teferi's Protege
19491 Vodalian Arcanist
19501 Read the Tides
19511 Talrand's Invocation
19521 Frost Breath
19531 Peel from Reality
19541 Rain of Revelation
19551 Wizard's Retort
19561 Thriving Isle
19577 Island ]]},
1958 }
1959}
1960
1961frameCounter = 0
1962cardNoInDeck = 0 -- not actual numbers, just a register
1963totalCards = 0
1964tokenCounter = 0 -- to discern between tokens
1965cardback_url_default = "https://s2.ax1x.com/2019/07/23/ekhc0P.jpg"
1966cardback_url_user = ""
1967cardback_url = "https://s2.ax1x.com/2019/07/23/ekhc0P.jpg"
1968decklist = ""
1969
1970options={
1971 searchText="",
1972 colorSet={
1973 white=false,
1974 blue=false,
1975 black=false,
1976 red=false,
1977 green=false,
1978 colorless=false
1979 },
1980 rarity={
1981 common=false,
1982 uncommon=false,
1983 rare=false,
1984 mythic=false
1985 },
1986 format="",
1987 expansion="",
1988 variation=false,
1989 type="",
1990 cmc=""
1991}
1992
1993title={
1994 tag="Text",
1995 attributes={
1996 color="white",
1997 fontSize=30
1998 },
1999 value="Filters"
2000}
2001
2002searchOption={
2003 tag="InputField",
2004 attributes={
2005 placeholder="search",
2006 onValueChanged="getSearchText"
2007 }
2008}
2009
2010function getSearchText(player, value, id)
2011 options['searchText'] = value
2012end
2013
2014colorOption={
2015 tag="GridLayout",
2016 attributes={
2017 cellSize="30 30",
2018 spacing="5 5"
2019 },
2020 children={
2021 {
2022 tag="Toggle",
2023 attributes={
2024 id="whiteToggle",
2025 onValueChanged="getColor"
2026 }
2027 },
2028 {
2029 tag="Image",
2030 attributes={
2031 image="white"
2032 }
2033 },
2034 {
2035 tag="Toggle",
2036 attributes={
2037 id="blueToggle",
2038 onValueChanged="getColor"
2039 }
2040 },
2041 {
2042 tag="Image",
2043 attributes={
2044 image="blue"
2045 }
2046 },
2047 {
2048 tag="Toggle",
2049 attributes={
2050 id="blackToggle",
2051 onValueChanged="getColor"
2052 }
2053 },
2054 {
2055 tag="Image",
2056 attributes={
2057 image="black"
2058 }
2059 },
2060 {
2061 tag="Toggle",
2062 attributes={
2063 id="redToggle",
2064 onValueChanged="getColor"
2065 }
2066 },
2067 {
2068 tag="Image",
2069 attributes={
2070 image="red"
2071 }
2072 },
2073 {
2074 tag="Toggle",
2075 attributes={
2076 id="greenToggle",
2077 onValueChanged="getColor"
2078 }
2079 },
2080 {
2081 tag="Image",
2082 attributes={
2083 image="green"
2084 }
2085 },
2086 {
2087 tag="Toggle",
2088 attributes={
2089 id="colorlessToggle",
2090 onValueChanged="getColorless"
2091 }
2092 },
2093 {
2094 tag="Image",
2095 attributes={
2096 image="colorless"
2097 }
2098 }
2099 }
2100}
2101
2102function getColor(player, value, id)
2103 options['colorSet']['colorless'] = false
2104 UI.setAttribute("colorlessToggle", "isOn", false)
2105 action = {
2106 ["whiteToggle"] = function() options['colorSet']['white'] = value end,
2107 ["blueToggle"] = function() options['colorSet']['blue'] = value end,
2108 ["blackToggle"] = function() options['colorSet']['black'] = value end,
2109 ["redToggle"] = function() options['colorSet']['red'] = value end,
2110 ["greenToggle"] = function() options['colorSet']['green'] = value end
2111 }
2112 action[id]()
2113end
2114
2115function getColorless(player, value, id)
2116 options['colorSet']['colorless'] = value
2117 options['colorSet']['white'] = false
2118 options['colorSet']['blue'] = false
2119 options['colorSet']['black'] = false
2120 options['colorSet']['red'] = false
2121 options['colorSet']['green'] = false
2122 UI.setAttribute("whiteToggle", "isOn", false)
2123 UI.setAttribute("blueToggle", "isOn", false)
2124 UI.setAttribute("blackToggle", "isOn", false)
2125 UI.setAttribute("redToggle", "isOn", false)
2126 UI.setAttribute("greenToggle", "isOn", false)
2127end
2128
2129spacer={
2130 tag="Text",
2131 attributes={
2132 color="white"
2133 },
2134 value=" "
2135}
2136
2137formatDropdown={
2138 tag="Dropdown",
2139 attributes={
2140 id="formatDropdown",
2141 scrollSensitivity="6",
2142 onValueChanged="dropdownTrigger"
2143 },
2144 children={
2145 {
2146 tag="Option",
2147 value="All Formats"
2148 },
2149 {
2150 tag="Option",
2151 value="Standard"
2152 },
2153 {
2154 tag="Option",
2155 value="Future Standard"
2156 },
2157 {
2158 tag="Option",
2159 value="Modern"
2160 },
2161 {
2162 tag="Option",
2163 value="Pioneer"
2164 },
2165 {
2166 tag="Option",
2167 value="Frontier"
2168 },
2169 {
2170 tag="Option",
2171 value="Legacy"
2172 },
2173 {
2174 tag="Option",
2175 value="Pauper"
2176 },
2177 {
2178 tag="Option",
2179 value="Vintage"
2180 },
2181 {
2182 tag="Option",
2183 value="Penny Dreadful"
2184 },
2185 {
2186 tag="Option",
2187 value="Commander"
2188 }
2189 }
2190}
2191
2192expansionDropdown={
2193 tag="Dropdown",
2194 attributes={
2195 height=30,
2196 id="expansionDropdown",
2197 scrollSensitivity="10",
2198 onValueChanged="dropdownTrigger"
2199 },
2200 children={
2201 {
2202 tag="Option",
2203 value="All Expansions"
2204 }
2205 }
2206}
2207
2208expansionTextBox={
2209 tag="InputField",
2210 attributes={
2211 id="expansionDropdown",
2212 placeholder="Set, e.g. IKO. Use either this or the dropdown to the left, but not both at the same time.",
2213 onValueChanged="dropdownTrigger"
2214 }
2215}
2216
2217variationOption={
2218 tag="GridLayout",
2219 attributes={
2220 cellSize="200 30"
2221 },
2222 children={
2223 {
2224 tag="ToggleButton",
2225 attributes={
2226 id="variationToggle",
2227 onValueChanged="variToggled",
2228 height="30"
2229 },
2230 value="Include Card Variants?"
2231 }
2232 }
2233}
2234
2235function variToggled()
2236 options['variation'] = not options['variation']
2237end
2238
2239rarityOption={
2240 tag="GridLayout",
2241 attributes={
2242 cellSize="80 30",
2243 spacing="5 5"
2244 },
2245 children={
2246 {
2247 tag="ToggleButton",
2248 attributes={
2249 id="common",
2250 onValueChanged="getRarity"
2251 },
2252 value="Common"
2253 },
2254 {
2255 tag="ToggleButton",
2256 attributes={
2257 id="uncommon",
2258 onValueChanged="getRarity"
2259 },
2260 value="Uncom."
2261 },
2262 {
2263 tag="ToggleButton",
2264 attributes={
2265 id="rare",
2266 onValueChanged="getRarity"
2267 },
2268 value="Rare"
2269 },
2270 {
2271 tag="ToggleButton",
2272 attributes={
2273 id="mythic",
2274 onValueChanged="getRarity"
2275 },
2276 value="Mythic"
2277 }
2278 }
2279}
2280
2281function getRarity(player, value, id)
2282 action = {
2283 ["common"] = function() options['rarity']['common'] = value end,
2284 ["uncommon"] = function() options['rarity']['uncommon'] = value end,
2285 ["rare"] = function() options['rarity']['rare'] = value end,
2286 ["mythic"] = function() options['rarity']['mythic'] = value end
2287 }
2288 action[id]()
2289end
2290
2291cmcOption={
2292 tag="InputField",
2293 attributes={
2294 placeholder="Converted mana cost, supports expression e.g. >2",
2295 onValueChanged="getCmc"
2296 }
2297}
2298
2299function getCmc(player, value, id)
2300 options['cmc'] = value
2301end
2302
2303typeDropdown={
2304 tag="InputField",
2305 attributes={
2306 id="typeDropdown",
2307 -- scrollSensitivity="8",
2308 placeholder="Card Type, put here enchantment, vehicle, merfolk etc.",
2309 onValueChanged="dropdownTrigger"
2310 }
2311}
2312
2313function dropdownTrigger(player, value, id)
2314 action = {
2315 ["formatDropdown"] = function() options['format'] = value end,
2316 ["expansionDropdown"] = function() options['expansion'] = value end,
2317 ["typeDropdown"] = function() options['type'] = value end,
2318 ["draftSetDropdown"] = function() draftSet = value end
2319 }
2320 action[id]()
2321end
2322
2323searchButton={
2324 tag="Button",
2325 attributes={
2326 height=30,
2327 width=100,
2328 color="blue",
2329 textColor="white",
2330 onClick="startSearch"
2331 },
2332 value="Search"
2333}
2334
2335resetDeckButton={
2336 tag="Button",
2337 attributes={
2338 height=30,
2339 width=100,
2340 color="rgba(0.57, 0.24, 0.24, 1)",
2341 textColor="white",
2342 onClick="resetDeck"
2343 },
2344 value="Reset Deck !"
2345}
2346
2347resetSearchButton={
2348 tag="Button",
2349 attributes={
2350 height=30,
2351 width=100,
2352 color="green",
2353 textColor="white",
2354 onClick="resetSearch"
2355 },
2356 value="Reset Search"
2357}
2358
2359refreshButton={
2360 tag="Button",
2361 attributes={
2362 height=30,
2363 width=100,
2364 color="green",
2365 textColor="white",
2366 onClick="refresh"
2367 },
2368 value="Refresh"
2369}
2370
2371exportButton={
2372 tag="Button",
2373 attributes={
2374 height=30,
2375 width=100,
2376 color="purple",
2377 textColor="white",
2378 onClick="exportDeck",
2379 id="exportButton"
2380 },
2381 value="Export (0 Cards in Deck)"
2382}
2383
2384closeButton={
2385 tag="Button",
2386 attributes={
2387 height=30,
2388 width=100,
2389 color="rgba(0.57, 0.24, 0.24, 1)",
2390 textColor="white",
2391 rectAlignment="MiddleRight",
2392 onClick="hideBuilder"
2393 },
2394 value="Close Builder X"
2395}
2396
2397cards={
2398 tag = "GridLayout",
2399 attributes = {
2400 cellSize = "300 418",
2401 spacing = "10 20",
2402 padding = "20 20 20 20",
2403 id = "cards"
2404 },
2405 children = {}
2406}
2407
2408deck={
2409 tag = "GridLayout",
2410 attributes = {
2411 cellSize = "150 210",
2412 spacing = "10 10",
2413 padding = "10 10 10 10",
2414 id = "deck"
2415 },
2416 children = {}
2417}
2418
2419boosterTable ={
2420 {
2421 tag="Panel",
2422 attributes={
2423 width=800,
2424 height=150,
2425 color="white"
2426 },
2427 children={
2428 {
2429 tag="VerticalLayout",
2430 attributes={
2431 height=150,
2432 padding="20 20 20 20",
2433 spacing="20"
2434 },
2435 children={
2436 {
2437 tag="Text",
2438 attributes={
2439 color="black",
2440 fontSize=20
2441 },
2442 value="Booster Pack Generator"
2443 },
2444 {
2445 tag="HorizontalLayout",
2446 children={
2447 {
2448 tag="Button",
2449 attributes={
2450 color="blue",
2451 textColor="white",
2452 onClick="openJumpstart"
2453 },
2454 value="Jumpstart (testing)"
2455 },
2456 {
2457 tag="Button",
2458 attributes={
2459 color="blue",
2460 textColor="white",
2461 onClick="openNormalPack"
2462 },
2463 value="Normal Booster (Post-ALA)"
2464 },
2465 {
2466 tag="Button",
2467 attributes={
2468 color="rgba(0.57, 0.24, 0.24, 1)",
2469 textColor="white",
2470 onClick="closeCardbackDialog"
2471 },
2472 value="Close"
2473 }
2474 }
2475 }
2476 }
2477 }
2478 }
2479 }
2480}
2481
2482jumpstartTable ={
2483 {
2484 tag="Panel",
2485 attributes={
2486 width=800,
2487 height=250,
2488 color="white"
2489 },
2490 children={
2491 {
2492 tag="VerticalLayout",
2493 attributes={
2494 height=250,
2495 padding="20 20 20 20",
2496 spacing="20"
2497 },
2498 children={
2499 {
2500 tag="Text",
2501 attributes={
2502 color="black",
2503 fontSize=20
2504 },
2505 value="Random Jumpstart Pack Generator"
2506 },
2507 {
2508 tag="Text",
2509 attributes={
2510 color="black",
2511 fontSize=15
2512 },
2513 value="How to play: Each player get two packs, mix them and play, no need for deckbuilding."
2514 },
2515 {
2516 tag="HorizontalLayout",
2517 children={
2518 {
2519 tag="InputField",
2520 attributes={
2521 placeholder="How many packs?",
2522 onValueChanged="packNumberTrigger"
2523 }
2524 },
2525 {
2526 tag="Button",
2527 attributes={
2528 color="green",
2529 textColor="white",
2530 onClick="addJmpPacks"
2531 },
2532 value="Add"
2533 },spacer,
2534 {
2535 tag="Button",
2536 attributes={
2537 color="rgba(0.57, 0.24, 0.24, 1)",
2538 textColor="white",
2539 onClick="openPackGenerator"
2540 },
2541 value="Return"
2542 }
2543 }
2544 },
2545 spacer
2546 }
2547 }
2548 }
2549 }
2550}
2551
2552normalPackTable = {
2553 {
2554 tag="Panel",
2555 attributes={
2556 width=800,
2557 height=250,
2558 color="white"
2559 },
2560 children={
2561 {
2562 tag="VerticalLayout",
2563 attributes={
2564 height=250,
2565 padding="20 20 20 20",
2566 spacing="20"
2567 },
2568 children={
2569 {
2570 tag="Text",
2571 attributes={
2572 color="black",
2573 fontSize=20
2574 },
2575 value="Normal Pack Generator (Post Shards of Alara)"
2576 },
2577 {
2578 tag="InputField",
2579 attributes={
2580 id="draftSetDropdown",
2581 placeholder="e.g., iko. Not every pack will show a symbol (it will give warnings just ignore).",
2582 onValueChanged="dropdownTrigger"
2583 }
2584 },
2585 {
2586 tag="HorizontalLayout",
2587 children={
2588 {
2589 tag="InputField",
2590 attributes={
2591 placeholder="How many packs?",
2592 onValueChanged="packNumberTrigger"
2593 }
2594 },
2595 {
2596 tag="Button",
2597 attributes={
2598 color="green",
2599 textColor="white",
2600 onClick="addPacks"
2601 },
2602 value="Add"
2603 },spacer,
2604 {
2605 tag="Button",
2606 attributes={
2607 color="rgba(0.57, 0.24, 0.24, 1)",
2608 textColor="white",
2609 onClick="openPackGenerator"
2610 },
2611 value="Return"
2612 }
2613 }
2614 },
2615 spacer
2616 }
2617 }
2618 }
2619 }
2620}
2621
2622builderTable = {
2623 {
2624 tag="Panel",
2625 attributes={
2626 color="white"
2627 },
2628 children={
2629 {
2630 -- Selection
2631 tag="VerticalLayout",
2632 attributes={
2633 height=230,
2634 spacing=10,
2635 rectAlignment="UpperLeft",
2636 padding="20 20 10 20",
2637 color="rgba(0.19, 0.19, 0.19, 1)",
2638 },
2639 children={
2640 title,
2641 {
2642 tag="HorizontalLayout",
2643 attributes={
2644 attributes={
2645 height=30
2646 },
2647 },
2648 children={
2649 searchOption, colorOption, formatDropdown, expansionDropdown, expansionTextBox
2650 }
2651 },
2652 {
2653 tag="HorizontalLayout",
2654 attributes={
2655 height=30,
2656 spacing=5
2657 },
2658 children={
2659 spacer, spacer, spacer, variationOption, rarityOption, cmcOption, typeDropdown
2660 }
2661 },
2662 {
2663 tag="HorizontalLayout",
2664 attributes={
2665 height=30,
2666 spacing=5
2667 },
2668 children={
2669 closeButton, resetDeckButton, spacer, spacer, spacer, refreshButton, resetSearchButton, exportButton, searchButton
2670 }
2671 }
2672 }
2673 },
2674 {
2675 tag = "VerticalScrollView",
2676 attributes = {
2677 width = 1920,
2678 height = 550,
2679 rectAlignment="MiddleLeft",
2680 movementType="Unrestricted",
2681 scrollSensitivity="15"
2682 },
2683 children = {
2684 cards
2685 }
2686 }
2687 ,
2688 {
2689 tag = "VerticalScrollView",
2690 attributes = {
2691 width = 1920,
2692 height = 250,
2693 rectAlignment="LowerLeft",
2694 movementType="Unrestricted",
2695 scrollSensitivity="10"
2696 },
2697 children={
2698 deck
2699 }
2700 },
2701 {
2702 tag = "ProgressBar",
2703 attributes = {
2704 rectAlignment="MiddleCenter",
2705 id="pbar",
2706 active="false"
2707 }
2708 },
2709 }
2710 }
2711}
2712
2713cardbackSelection ={
2714 {
2715 tag="Panel",
2716 attributes={
2717 width=800,
2718 height=200,
2719 color="white"
2720 },
2721 children={
2722 {
2723 tag="VerticalLayout",
2724 attributes={
2725 height=200,
2726 padding="20 20 20 20",
2727 spacing="20"
2728 },
2729 children={
2730 {
2731 tag="InputField",
2732 attributes={
2733 placeholder="Enter your image url here...",
2734 onValueChanged="saveCardbackUrl"
2735 }
2736 },
2737 {
2738 tag="HorizontalLayout",
2739 children={
2740 {
2741 tag="Button",
2742 attributes={
2743 color="green",
2744 textColor="white",
2745 onClick="applyCardback"
2746 },
2747 value="Apply"
2748 },
2749 {
2750 tag="Button",
2751 attributes={
2752 color="blue",
2753 textColor="white",
2754 onClick="useDefaultCardback"
2755 },
2756 value="Use Default"
2757 },
2758 {
2759 tag="Button",
2760 attributes={
2761 color="rgba(0.57, 0.24, 0.24, 1)",
2762 textColor="white",
2763 onClick="closeCardbackDialog"
2764 },
2765 value="Cancel"
2766 }
2767 }
2768 },
2769 {
2770 tag="Text",
2771 value="Click Apply to use custom cardback from the url. Use default will reset to the default cardback."
2772 }
2773 }
2774 }
2775 }
2776 }
2777}
2778
2779function packNumberTrigger(player, value, id)
2780 packNumber = value
2781end
2782
2783setSymbols = {
2784 jmp = "https://s1.ax1x.com/2020/06/24/Nd5IgI.png",
2785 m21 = "https://s1.ax1x.com/2020/06/22/NGsAsK.png",
2786 iko = "https://s1.ax1x.com/2020/04/14/GzAaP1.png",
2787 thb = "https://s2.ax1x.com/2020/01/11/l5riWD.png",
2788 eld = "https://s2.ax1x.com/2020/01/06/lsj17d.png",
2789 m20 = "https://s2.ax1x.com/2020/01/04/l0EVSI.png",
2790 war = "https://s2.ax1x.com/2020/01/04/l0EJlq.png",
2791 rna = "https://s2.ax1x.com/2020/01/04/l0EMTg.png",
2792 grn = "https://s2.ax1x.com/2020/01/04/l0ESOK.png",
2793 m19 = "https://s2.ax1x.com/2020/01/04/l0EAfA.png",
2794 dom = "https://s2.ax1x.com/2020/01/04/l0AXWR.png",
2795 rix = "https://s2.ax1x.com/2020/01/04/l0EK0S.png",
2796 xln = "https://s2.ax1x.com/2020/01/04/l0EtXV.png",
2797 hou = "https://s2.ax1x.com/2020/01/04/l0ECwD.png",
2798 akh = "https://s2.ax1x.com/2020/01/04/l0Ed7F.png",
2799 aer = "https://s2.ax1x.com/2020/01/04/l0Ea0U.png",
2800 kld = "https://s2.ax1x.com/2020/01/04/l0EFFH.png",
2801 emn = "https://s2.ax1x.com/2020/01/04/l0AvS1.png",
2802 soi = "https://s2.ax1x.com/2020/01/04/l0E1Yj.png",
2803 ogw = "https://s2.ax1x.com/2020/01/04/l0EmOf.png",
2804 bfz = "https://s2.ax1x.com/2020/01/04/l0EBtJ.png",
2805 ori = "https://s2.ax1x.com/2020/01/04/l0Eum8.png",
2806 dtk = "https://s2.ax1x.com/2020/01/04/l0AOY9.png",
2807 frf = "https://s2.ax1x.com/2020/01/04/l0ALFJ.png",
2808 ktk = "https://s2.ax1x.com/2020/01/04/l0EkYd.png",
2809 avr = "https://s2.ax1x.com/2020/01/04/l0E0k4.png",
2810 dka = "https://s2.ax1x.com/2020/01/04/l0AxQx.png",
2811 isd = "https://s2.ax1x.com/2020/01/04/l0EPTe.png",
2812 nph = "https://s2.ax1x.com/2020/01/04/l0Ee6P.png",
2813 mbs = "https://s2.ax1x.com/2020/01/04/l0EZlt.png",
2814 som = "https://s2.ax1x.com/2020/01/04/l0EZlt.png",
2815 roe = "https://s2.ax1x.com/2020/01/04/l0ElkQ.png",
2816 wwk = "https://s2.ax1x.com/2020/01/04/l0EY60.png",
2817 zen = "https://s2.ax1x.com/2020/01/04/l0EUmT.png",
2818}
2819
2820-- normal booster pack adding
2821function addPacksFunc()
2822 setAbbreviation = draftSet:gsub("%s%w+", "")
2823 print('Worker started for '..setAbbreviation)
2824 math.randomseed(os.time())
2825 if not booster[setAbbreviation] then
2826 WebRequest.get("https://api.scryfall.com/cards/search?order=rarity&q=set%3A"..setAbbreviation.."+rarity=mythic+is%3Abooster", function(arg) setDraftCallback(arg, 'mythic', setAbbreviation) end)
2827 coroutine.yield()
2828 WebRequest.get("https://api.scryfall.com/cards/search?order=rarity&q=set%3A"..setAbbreviation.."+rarity=rare+is%3Abooster", function(arg) setDraftCallback(arg, 'rare', setAbbreviation) end)
2829 coroutine.yield()
2830 WebRequest.get("https://api.scryfall.com/cards/search?order=rarity&q=set%3A"..setAbbreviation.."+rarity=uncommon+is%3Abooster", function(arg) setDraftCallback(arg, 'uncommon', setAbbreviation) end)
2831 coroutine.yield()
2832 WebRequest.get("https://api.scryfall.com/cards/search?order=rarity&q=set%3A"..setAbbreviation.."+rarity=common+is%3Abooster", function(arg) setDraftCallback(arg, 'common', setAbbreviation) end)
2833 coroutine.yield()
2834 end
2835 print("creating packs, pls wait")
2836 local mythics = 0
2837 for i=1,packNumber,1 do
2838 if math.random() < 0.125 then mythics = mythics + 1 end
2839 end
2840 boosterCards = {['mythicOrRare'] = {}, ['uncommon'] = {}, ['common'] = {}}
2841 local mythic_totalCards = booster[setAbbreviation]['mythic']['total_cards']
2842 print("total mythic: "..mythic_totalCards)
2843 local rare_totalCards = booster[setAbbreviation]['rare']['total_cards']
2844 print("total rare: "..rare_totalCards)
2845 local uncommon_totalCards = booster[setAbbreviation]['uncommon']['total_cards']
2846 print("total uncommon: "..uncommon_totalCards)
2847 local common_totalCards = booster[setAbbreviation]['common']['total_cards']
2848 print("total common: "..common_totalCards)
2849 for i=1,mythics do
2850 table.insert(boosterCards['mythicOrRare'], booster[setAbbreviation]['mythic']['data'][math.random(mythic_totalCards)]['name'])
2851 end
2852 for i=1,packNumber-mythics do
2853 table.insert(boosterCards['mythicOrRare'], booster[setAbbreviation]['rare']['data'][math.random(rare_totalCards)]['name'])
2854 end
2855 uncom = {}
2856 for i=1,packNumber*3 do
2857 tempRandomNumber = math.random(uncommon_totalCards)
2858 while(uncom[tempRandomNumber]==0) do
2859 tempRandomNumber = math.random(uncommon_totalCards)
2860 end
2861 uncom[tempRandomNumber] = 0
2862 table.insert(boosterCards['uncommon'], booster[setAbbreviation]['uncommon']['data'][tempRandomNumber]['name'])
2863 end
2864 com = {}
2865 for i=1,packNumber*11 do
2866 tempRandomNumber = math.random(common_totalCards)
2867 while(uncom[tempRandomNumber]==0) do
2868 tempRandomNumber = math.random(common_totalCards)
2869 end
2870 com[tempRandomNumber] = 0
2871 table.insert(boosterCards['common'], booster[setAbbreviation]['common']['data'][tempRandomNumber]['name'])
2872 end
2873 for i=1,packNumber do
2874 local packObj = getObjectFromGUID("e2c21a").clone()
2875 local params = {
2876 name = "API Icon",
2877 url = setSymbols[setAbbreviation],
2878 position = {0, 0.15, 0},
2879 rotation = {90, -90, 0},
2880 scale = {0.7, 1, 1},
2881 }
2882 packObj.addDecal(params)
2883 local pos = {-20+5*i, 3,-10}
2884 packObj.setPosition(pos)
2885 local header = "https://api.scryfall.com/cards/named?exact="
2886 -- Mythic or Rare
2887 WebRequest.get(header..boosterCards['mythicOrRare'][i].."&set="..setAbbreviation, function(arg) getCardPic(arg, boosterCards['mythicOrRare'][i], pos) end)
2888 -- uncommon
2889 for j=3*i-2,3*i do
2890 WebRequest.get(header..boosterCards['uncommon'][j].."&set="..setAbbreviation, function(arg) getCardPic(arg, boosterCards['uncommon'][j], pos) end)
2891 end
2892 -- commons
2893 for k=11*i-10,11*i do
2894 WebRequest.get(header..boosterCards['common'][k].."&set="..setAbbreviation, function(arg) getCardPic(arg, boosterCards['common'][k], pos) end)
2895 end
2896 end
2897end
2898
2899co = nil
2900
2901function addPacks()
2902 print('starting coroutine')
2903 co = coroutine.create(addPacksFunc)
2904 coroutine.resume(co)
2905end
2906
2907function setDraftCallback(arg, rarity, setAbbreviation)
2908 if arg.is_done then
2909 local cardsSameRarity = luaJson.json2lua(arg.text)
2910 -- local totalCards = cardsSameRarity['total_cards']
2911 if rarity == 'mythic' then
2912 print('getting mythics')
2913 booster[setAbbreviation] = {}
2914 booster[setAbbreviation]['mythic'] = cardsSameRarity
2915 coroutine.resume(co)
2916 end
2917 if rarity == 'rare' then
2918 print('getting rares')
2919 booster[setAbbreviation]['rare'] = cardsSameRarity
2920 coroutine.resume(co)
2921 end
2922 if rarity == 'uncommon' then
2923 print('getting uncommons')
2924 booster[setAbbreviation]['uncommon'] = cardsSameRarity
2925 coroutine.resume(co)
2926 end
2927 if rarity == 'common' then
2928 print('getting commons')
2929 booster[setAbbreviation]['common'] = cardsSameRarity
2930 coroutine.resume(co)
2931 end
2932 end
2933end
2934
2935--- Jumpstart packs
2936function addJmpPacks()
2937 for i=1,packNumber do
2938 local packObj = getObjectFromGUID("e2c21a").clone()
2939 local params = {
2940 name = "API Icon",
2941 url = setSymbols['jmp'],
2942 position = {0, 0.15, 0},
2943 rotation = {90, -90, 0},
2944 scale = {0.7, 1, 1},
2945 }
2946 packObj.addDecal(params)
2947 local pos = {-20+5*i, 3,-10}
2948 packObj.setPosition(pos)
2949 decklist = jmp['decks'][math.random(121)]['text']
2950 importDeckWithPosition(pos)
2951 end
2952end
2953
2954
2955function saveCardbackUrl(player, value, id)
2956 cardback_url_user = value
2957end
2958
2959function applyCardback()
2960 cardback_url = cardback_url_user
2961 closeCardbackDialog()
2962end
2963
2964function useDefaultCardback()
2965 cardback_url = cardback_url_default
2966 closeCardbackDialog()
2967end
2968
2969function closeCardbackDialog()
2970 UI.setXmlTable(initialUI)
2971end
2972
2973deckImport = {
2974 {
2975 tag = "Panel",
2976 attributes={
2977 width=800,
2978 height=600,
2979 color="white"
2980 },
2981 children={
2982 {
2983 tag="HorizontalLayout",
2984 attributes={
2985 padding="20 20 20 20",
2986 spacing="20",
2987 },
2988 children={
2989 {
2990 tag="GridLayout",
2991 attributes={
2992 cellSize="550 560"
2993 },
2994 children={
2995 {
2996 tag="InputField",
2997 attributes={
2998 lineType="MultiLineNewLine",
2999 placeholder="Put your deck here:\nFormat: # Card Name (Set) \nExample:\n4 Rekindling Phoenix\n1 Mountain \n1 Black Lotus (LEA)",
3000 onValueChanged="saveDecklist",
3001 id="decklist"
3002 }
3003 }
3004 }
3005 },
3006 {
3007 tag="GridLayout",
3008 attributes={
3009 cellSize="200 50"
3010 },
3011 children={
3012 {
3013 tag="Button",
3014 attributes={
3015 textColor="white",
3016 color="blue",
3017 onClick="importDeck"
3018 },
3019 value="Import"
3020 },
3021 {
3022 tag="Button",
3023 attributes={
3024 color="rgba(0.57, 0.24, 0.24, 1)",
3025 textColor="white",
3026 onClick="closeDeckImport"
3027 },
3028 value="Cancel"
3029 }
3030 }
3031 }
3032 }
3033 },
3034 }
3035 }
3036}
3037
3038function saveDecklist(player, value, id)
3039 decklist = value
3040end
3041
3042function importDeck()
3043 local lineByLine = {}
3044 local header = "https://api.scryfall.com/cards/named?exact="
3045 for str in string.gmatch(decklist, "([^".."\n".."]+)") do
3046 table.insert(lineByLine, str)
3047 end
3048 for key, entry in pairs(lineByLine) do
3049 if(string.match(entry, "Sideboard")=="Sideboard") then
3050
3051 else
3052 cardNo = string.match(entry, "%d+%s")
3053 cardName_set = entry:gsub('%d+%s','')
3054 set = cardName_set:match('%(%w+%)')
3055 cardName = cardName_set:gsub('%s%(%w+%)','')
3056 for i=cardNo,1,-1 do
3057 if (set) then
3058 set = set:match('%w+')
3059 WebRequest.get(header..cardName.."&set="..set, function(arg) getCardPic(arg, cardName) end)
3060 else
3061 WebRequest.get(header..cardName, function(arg) getCardPic(arg, cardName) end)
3062 end
3063 Wait.frames(function() end, 7)
3064 end
3065 end
3066 end
3067end
3068
3069function importDeckWithPosition(pos)
3070 local lineByLine = {}
3071 local header = "https://api.scryfall.com/cards/named?exact="
3072 for str in string.gmatch(decklist, "([^".."\n".."]+)") do
3073 table.insert(lineByLine, str)
3074 end
3075 for key, entry in pairs(lineByLine) do
3076 if(string.match(entry, "Sideboard")=="Sideboard") then
3077
3078 else
3079 cardNo = string.match(entry, "%d+%s")
3080 cardName_set = entry:gsub('%d+%s','')
3081 set = cardName_set:match('%(%w+%)')
3082 cardName = cardName_set:gsub('%s%(%w+%)','')
3083 for i=cardNo,1,-1 do
3084 if (set) then
3085 set = set:match('%w+')
3086 WebRequest.get(header..cardName.."&set="..set, function(arg) getCardPic(arg, cardName, pos) end)
3087 else
3088 WebRequest.get(header..cardName, function(arg) getCardPic(arg, cardName, pos) end)
3089 end
3090 Wait.frames(function() end, 7)
3091 end
3092 end
3093 end
3094end
3095
3096function getCardPic(arg, cardName, pos)
3097 if(arg.is_error) then
3098 print("error")
3099 end
3100 local cardsTable = {}
3101 if(arg.is_done) then
3102 pos = pos or {0, 0, 0}
3103 local card = luaJson.json2lua(arg.text)
3104 local layout = card['layout']
3105 local url_face = ""
3106 local url_back = cardback_url
3107 if layout=="transform" or layout=="modal_dfc" then
3108 url_face = card['card_faces'][1]['image_uris']['large']:gsub('?d%+','')
3109 url_back = card['card_faces'][2]['image_uris']['large']:gsub('?d%+','')
3110 spawnedCard = spawnObject({type="Card",rotation={x=0, y=180, z=0}, position=pos})
3111 spawnedCard.setCustomObject({
3112 face=url_face,
3113 back=cardback_url
3114 })
3115 spawnedCard.setName(card['name'].."token")
3116 spawnedCard = spawnObject({type="Card",rotation={x=0, y=180, z=0},position={x=3, y=3, z=0}})
3117 spawnedCard.setCustomObject({
3118 face=url_face,
3119 back=url_back
3120 })
3121 spawnedCard.setName(card['name'])
3122 else
3123 url_face = card['image_uris']['large']
3124 spawnedCard = spawnObject({type="Card",rotation={x=0, y=180, z=0}, position=pos})
3125 spawnedCard.setCustomObject({
3126 face=url_face,
3127 back=url_back
3128 })
3129 spawnedCard.setName(card['name'])
3130 end
3131 end
3132end
3133
3134function closeDeckImport()
3135 UI.setXmlTable(initialUI)
3136end
3137
3138assets = {
3139 {
3140 name = "white",
3141 url = "https://s2.ax1x.com/2019/07/09/ZyTui4.jpg"
3142 },
3143 {
3144 name = "blue",
3145 url = "https://s2.ax1x.com/2019/07/09/ZyTmoF.jpg"
3146 },
3147 {
3148 name = "black",
3149 url = "https://s2.ax1x.com/2019/07/09/ZyTMW9.jpg"
3150 },
3151 {
3152 name = "red",
3153 url = "https://s2.ax1x.com/2019/07/09/ZyTKJJ.jpg"
3154 },
3155 {
3156 name = "green",
3157 url = "https://s2.ax1x.com/2019/07/10/ZcYFk4.jpg"
3158 },
3159 {
3160 name = "colorless",
3161 url = "https://s2.ax1x.com/2019/07/09/ZyT7wT.png"
3162 }
3163}
3164
3165initialUI = {
3166 {
3167 tag="VerticalLayout",
3168 attributes={
3169 rectAlignment="LowerRight",
3170 spacing="20",
3171 height=240,
3172 width=100
3173 },
3174 children={
3175 {
3176 tag="Button",
3177 attributes={
3178 height=30,
3179 width=100,
3180 color="blue",
3181 textColor="white",
3182 onClick="openPackGenerator"
3183 },
3184 value="Booster pack"
3185 },
3186 {
3187 tag="Button",
3188 attributes={
3189 height=30,
3190 width=100,
3191 color="blue",
3192 textColor="white",
3193 onClick="openBuilder"
3194 },
3195 value="Open Builder"
3196 },
3197 {
3198 tag="Button",
3199 attributes={
3200 height=30,
3201 width=100,
3202 color="blue",
3203 textColor="white",
3204 onClick="openImport"
3205 },
3206 value="Import from text"
3207 },
3208 {
3209 tag="Button",
3210 attributes={
3211 height=30,
3212 width=100,
3213 color="blue",
3214 textColor="white",
3215 onClick="openCardbackSelection"
3216 },
3217 value="Select Cardback"
3218 },
3219 {
3220 tag="Button",
3221 attributes={
3222 height=30,
3223 width=100,
3224 color="green",
3225 textColor="white",
3226 onClick="hideInitialUI"
3227 },
3228 value="Hide Buttons"
3229 }
3230 }
3231 }
3232}
3233
3234secondaryUI = {
3235 {
3236 tag="VerticalLayout",
3237 attributes={
3238 rectAlignment="LowerRight",
3239 spacing="20",
3240 height=30,
3241 width=100
3242 },
3243 children={
3244 {
3245 tag="Button",
3246 attributes={
3247 height=30,
3248 width=100,
3249 color="green",
3250 textColor="white",
3251 onClick="showInitialUI"
3252 },
3253 value="Show Buttons"
3254 }
3255 }
3256 }
3257}
3258
3259--[[ The onLoad event is called after the game save finishes loading. --]]
3260function onLoad()
3261 Lighting.light_intensity = 0
3262 UI.setCustomAssets(assets)
3263 UI.setXmlTable(initialUI)
3264 for key,value in pairs(luaJson.json2lua(expansions)) do
3265 table.insert(expansionDropdown['children'], {
3266 tag="option",
3267 value=value['code'] .. " " .. value['name']
3268 })
3269 end
3270end
3271
3272--[[ The onUpdate event is called once per frame. --]]
3273function onUpdate()
3274 frameCounter = frameCounter + 1
3275end
3276
3277function openPackGenerator()
3278 UI.setXmlTable(boosterTable)
3279end
3280function openNormalPack()
3281 UI.setXmlTable(normalPackTable)
3282end
3283function openJumpstart()
3284 UI.setXmlTable(jumpstartTable)
3285end
3286
3287function openBuilder()
3288 UI.setXmlTable(builderTable)
3289end
3290
3291function hideInitialUI()
3292 UI.setXmlTable(secondaryUI)
3293end
3294
3295function showInitialUI()
3296 UI.setXmlTable(initialUI)
3297end
3298
3299function openCardbackSelection()
3300 UI.setXmlTable(cardbackSelection)
3301end
3302
3303function openImport()
3304 UI.setXmlTable(deckImport)
3305end
3306
3307function hideBuilder()
3308 UI.setXmlTable(initialUI)
3309 options={
3310 searchText="",
3311 colorSet={
3312 white=false,
3313 blue=false,
3314 black=false,
3315 red=false,
3316 green=false,
3317 colorless=false
3318 },
3319 rarity={
3320 common=false,
3321 uncommon=false,
3322 rare=false,
3323 mythic=false
3324 },
3325 format="",
3326 expansion="",
3327 variation=false,
3328 type="",
3329 cmc=""
3330 }
3331end
3332
3333function resetSearch()
3334 cards['children']={}
3335 refresh()
3336end
3337
3338function refresh()
3339 UI.setAttribute("pbar", "active", false)
3340 openBuilder()
3341 options['searchText']=""
3342 options['colorSet']={
3343 white=false,
3344 blue=false,
3345 black=false,
3346 red=false,
3347 green=false,
3348 colorless=false
3349 }
3350 options['format'] = ""
3351 options['expansion'] = ""
3352 options['variation'] = false
3353 options['type'] = ""
3354 options['cmc'] = ""
3355end
3356
3357function startSearch()
3358 UI.setAttribute("pbar", "active", true)
3359 local header = "https://api.scryfall.com/cards/search?q="
3360 local body = options['searchText']
3361 local col = ""
3362 local set = ""
3363 local rarity = ""
3364 local raritySeperator = "+OR+rarity="
3365
3366 if(options['colorSet']['white']) then col = col .. "w" end
3367 if(options['colorSet']['blue']) then col = col .. "u" end
3368 if(options['colorSet']['black']) then col = col .. "b" end
3369 if(options['colorSet']['red']) then col = col .. "r" end
3370 if(options['colorSet']['green']) then col = col .. "g" end
3371 if(options['colorSet']['colorless']) then col = "c" end
3372 if(col~="") then body = body .. "+color=" .. col end
3373
3374 if(options['cmc']~="") then body = body .. "+cmc" .. options['cmc'] end
3375
3376 if(string.sub(options['format'], 1, 3) ~= "All" and string.sub(options['format'], 1, 3) ~= "") then body = body .. "+legal=" .. options['format'] end
3377
3378 if(string.sub(options['expansion'], 1, 3) ~= "All" and string.sub(options['expansion'], 1, 3) ~= "") then
3379 for i = 1, string.len(options['expansion']) do
3380 if(string.sub(options['expansion'], i, i) ~=' ') then
3381 set = set .. string.sub(options['expansion'], i, i)
3382 else
3383 break
3384 end
3385 end
3386 body = body .. "+set=" .. set
3387 options['expansion'] = set
3388 end
3389
3390 if(options['rarity']['common']) then rarity = "c" end
3391 if(options['rarity']['uncommon']) then rarity = rarity == "" and "u" or (rarity .. raritySeperator .. "u") end
3392 if(options['rarity']['rare']) then rarity = rarity == "" and "r" or (rarity .. raritySeperator .. "r") end
3393 if(options['rarity']['mythic']) then rarity = rarity == "" and "m" or (rarity .. raritySeperator .. "m") end
3394 if(rarity ~= "") then body = body .. "+(rarity=" .. rarity .. ")" end
3395
3396 if(string.sub(options['type'], 1, 3) ~= "All" and string.sub(options['type'], 1, 3) ~= "") then body = body .. "+type=" .. options['type'] end
3397
3398 print(header..body)
3399 WebRequest.get(header..body, function(arg) searchCardsCallback(arg, options['variation']) end)
3400end
3401
3402function searchCardsCallback(arg, searchingForVariation)
3403 if(arg.is_error) then
3404 print("error")
3405 end
3406 if(arg.is_done) then
3407 UI.setAttribute("pbar", "percentage", 50.0)
3408 print("Fetch complete. Decoding...")
3409 cardsTable = luaJson.json2lua(arg.text)
3410 -- Card variations
3411 if searchingForVariation then
3412 for i=cardsTable['total_cards'],1,-1 do
3413 if cardsTable['data'][i]['type_line']=="Basic Land — "..cardsTable['data'][i]['name'] then
3414 -- print(cardsTable['data'][i]['prints_search_uri']:gsub('&q=','&q=set='..options['expansion']..'+'))
3415 local searchVariationUrl = cardsTable['data'][i]['prints_search_uri']:gsub('\\u0026','&')
3416 WebRequest.get(searchVariationUrl:gsub('&q=','&q=set='..options['expansion']..'+'), function(arg) searchCardsCallback(arg, false) end)
3417 else
3418 local searchVariationUrl = cardsTable['data'][i]['prints_search_uri']:gsub('\\u0026','&')
3419 WebRequest.get(searchVariationUrl, function(arg) searchCardsCallback(arg, false) end)
3420 end
3421 end
3422 else
3423 variationCount = 0
3424 for key,value in pairs(cardsTable['data']) do
3425 -- print(value['name'])
3426 -- print(value['image_uris']['png'])
3427 if options['variation'] then
3428 table.insert(cards['children'], createCardTable(value, variationCount))
3429 variationCount = variationCount + 1
3430 else
3431 table.insert(cards['children'], createCardTable(value, ''))
3432 end
3433 end
3434 UI.setAttribute("pbar", "percentage", 90)
3435 Wait.frames(refresh, 60)
3436 end
3437 -- More pages
3438 if cardsTable["has_more"] then
3439 WebRequest.get(cardsTable["next_page"]:gsub('\\u0026','&'), function(arg) searchCardsCallback(arg, false) end)
3440 end
3441 end
3442end
3443
3444function createCardTable(entry, additionalDescriber)
3445 local name = entry['name']:gsub("%s+", ""):gsub('\\"',"")
3446 local layout = entry['layout']
3447 if layout=="transform" or layout=="modal_dfc" then
3448 table.insert(assets, {
3449 name = name..additionalDescriber..'^face' ,
3450 url = entry['card_faces'][1]['image_uris']['large']:gsub('?%d+','')
3451 })
3452 table.insert(assets, {
3453 name = name..additionalDescriber..'^back' ,
3454 url = entry['card_faces'][2]['image_uris']['large']:gsub('?%d+','')
3455 })
3456 UI.setCustomAssets(assets)
3457 return
3458 {
3459 tag = "Button",
3460 attributes = {
3461 icon = name..additionalDescriber..'^face',
3462 id = name..additionalDescriber..'^face',
3463 onclick = "addCardToDeck"
3464 }
3465 }
3466 else
3467 if layout=="token" then
3468 additionalDescriber=additionalDescriber.."tk"..tokenCounter
3469 tokenCounter = tokenCounter+1
3470 table.insert(assets, {
3471 name = name..additionalDescriber,
3472 url = entry['image_uris']['large']:gsub('?%d+','')
3473 })
3474 UI.setCustomAssets(assets)
3475 return
3476 {
3477 tag = "Button",
3478 attributes = {
3479 icon = name..additionalDescriber,
3480 id = name..additionalDescriber,
3481 onclick = "addCardToDeck"
3482 }
3483 }
3484 else
3485 if layout=="double_faced_token" then
3486 table.insert(assets, {
3487 name = name..additionalDescriber..'^face' ,
3488 url = entry['card_faces'][1]['image_uris']['large']:gsub('?%d+','')
3489 })
3490 table.insert(assets, {
3491 name = name..additionalDescriber..'^back' ,
3492 url = entry['card_faces'][2]['image_uris']['large']:gsub('?%d+','')
3493 })
3494 UI.setCustomAssets(assets)
3495 return
3496 {
3497 tag = "Button",
3498 attributes = {
3499 icon = name..additionalDescriber,
3500 id = name..additionalDescriber,
3501 onclick = "addCardToDeck"
3502 }
3503 }
3504 end
3505 end
3506 end
3507end
3508
3509-- Deck related
3510
3511function addCardToDeck(player, value, id)
3512 cardNoInDeck = cardNoInDeck + 1
3513 totalCards = totalCards + 1
3514 exportButton['value'] = "Export ("..totalCards.." Cards in Deck)"
3515 table.insert(deck['children'], {
3516 tag = "Button",
3517 attributes = {
3518 icon = id,
3519 onclick = "removeCardFromDeck",
3520 id = tostring(cardNoInDeck)
3521 }
3522 })
3523 refresh()
3524end
3525
3526function removeCardFromDeck(player, value, id)
3527 for k, v in pairs(deck['children']) do
3528 if(v['attributes']['id'] == id) then
3529 table.remove(deck['children'], k)
3530 break
3531 end
3532 end
3533 totalCards = totalCards - 1
3534 exportButton['value'] = "Export ("..totalCards.." Cards in Deck)"
3535 refresh()
3536end
3537
3538function exportDeck()
3539 for k, v in pairs(deck['children']) do
3540 sep = "^"
3541 res = {}
3542 for st in string.gmatch(v['attributes']['icon'], "([^"..sep.."]+)") do
3543 table.insert(res, st)
3544 end
3545 -- Dealing with dfc
3546 if res[2]==nil then
3547 url = ""
3548 for ak, av in pairs(assets) do
3549 if av['name']==v['attributes']['icon'] then url = av['url']:gsub('?d%+','') end
3550 end
3551 spawnedCard = spawnObject({type="Card",rotation={x=0, y=180, z=0}})
3552 spawnedCard.setCustomObject({
3553 face=url,
3554 back=cardback_url
3555 })
3556 spawnedCard.setName(v['attributes']['icon'])
3557 spawnedCard.reload()
3558 else
3559 url_face = ""
3560 url_back = ""
3561 for ak, av in pairs(assets) do
3562 if av['name']==res[1].."^face" then url_face = av['url']:gsub('?d%+','') end
3563 if av['name']==res[1].."^back" then url_back = av['url']:gsub('?d%+','') end
3564 end
3565 spawnedCard = spawnObject({type="Card",rotation={x=0, y=180, z=0}, position={x=3, y=3, z=0}})
3566 spawnedCard.setCustomObject({
3567 face=url_face,
3568 back=url_back
3569 })
3570 spawnedCard.setName(v['attributes']['icon'])
3571 spawnedCard = spawnObject({type="Card",rotation={x=0, y=180, z=0}})
3572 spawnedCard.setCustomObject({
3573 face=url_face,
3574 back=cardback_url
3575 })
3576 spawnedCard.setName(v['attributes']['icon'].."_token")
3577 spawnedCard.reload()
3578 end
3579 end
3580end
3581
3582function resetDeck()
3583 deck['children'] = {}
3584 totalCards = 0
3585 exportButton['value'] = "Export ("..totalCards.." Cards in Deck)"
3586 refresh()
3587end
3588