├── .github
└── workflows
│ └── update.yml
├── .pkgmeta
├── Database
├── Druid.lua
├── Hunter.lua
├── HunterPets.lua
├── Mage.lua
├── Paladin.lua
├── Priest.lua
├── Rogue.lua
├── Shaman.lua
├── Trainers.lua
├── Warlock.lua
├── WarlockPets.lua
├── Warrior.lua
└── WeaponSkills.lua
├── FieldGuide.lua
├── FieldGuide.toc
├── FieldGuide.xml
├── LICENSE
├── Libraries
├── CallbackHandler-1.0
│ └── CallbackHandler-1.0.lua
├── HereBeDragons-2.0
│ ├── HereBeDragons-2.0.lua
│ └── HereBeDragons-Pins-2.0.lua
├── LibDBIcon-1.0
│ └── LibDBIcon-1.0.lua
├── LibDataBroker-1.1
│ └── LibDataBroker-1.1.lua
├── LibStub
│ └── LibStub.lua
└── LibUIDropDownMenu
│ ├── LibEasyMenu.lua
│ ├── LibUIDropDownMenu.lua
│ ├── LibUIDropDownMenu.xml
│ ├── LibUIDropDownMenuTemplates.lua
│ └── LibUIDropDownMenuTemplates.xml
├── Media
├── Background
│ ├── Background.tga
│ └── Separator.tga
├── Buttons
│ ├── ScrollDownButton-Disabled.tga
│ ├── ScrollDownButton-Down.tga
│ ├── ScrollDownButton-Highlight.tga
│ ├── ScrollDownButton-Up.tga
│ ├── ScrollLeftButton-Disabled.tga
│ ├── ScrollLeftButton-Down.tga
│ ├── ScrollLeftButton-Highlight.tga
│ ├── ScrollLeftButton-Up.tga
│ ├── ScrollRightButton-Disabled.tga
│ ├── ScrollRightButton-Down.tga
│ ├── ScrollRightButton-Highlight.tga
│ ├── ScrollRightButton-Up.tga
│ ├── ScrollUpButton-Disabled.tga
│ ├── ScrollUpButton-Down.tga
│ ├── ScrollUpButton-Highlight.tga
│ ├── ScrollUpButton-Up.tga
│ ├── ScrollbarHorizontal-Knob.tga
│ ├── ScrollbarVertical-Knob.tga
│ ├── SpellBackground.tga
│ └── SpellHighlight.tga
└── Map
│ └── GoldGreenDot.tga
├── README.md
└── Util.lua
/.github/workflows/update.yml:
--------------------------------------------------------------------------------
1 | name: Package and release
2 |
3 | on:
4 | push:
5 | tags:
6 | - '**'
7 |
8 | jobs:
9 |
10 | release:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | env:
15 | CF_API_KEY: ${{ secrets.CF_API_KEY }}
16 | WOWI_API_TOKEN: ${{ secrets.WOWI_API_TOKEN }}
17 | GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }}
18 |
19 | steps:
20 |
21 | - name: Clone project
22 | uses: actions/checkout@v3
23 | with:
24 | fetch-depth: 0
25 |
26 | - name: Package and release
27 | uses: BigWigsMods/packager@v2
28 |
--------------------------------------------------------------------------------
/.pkgmeta:
--------------------------------------------------------------------------------
1 | package-as: FieldGuide
2 |
3 | ignore:
4 | - README.md
--------------------------------------------------------------------------------
/Database/HunterPets.lua:
--------------------------------------------------------------------------------
1 | local _, FieldGuide = ...
2 |
3 | FieldGuide.HUNTER_PETS = {
4 | [2] = {
5 | [1] = {
6 | ["name"] = "Growl",
7 | ["rank"] = 1,
8 | ["cost"] = 0,
9 | ["texture"] = "Interface/ICONS/ability_physical_taunt",
10 | ["id"] = 2649
11 | },
12 | },
13 | [4] = {
14 | { empty = true }
15 | },
16 | [6] = {
17 | { empty = true }
18 | },
19 | [8] = {
20 | { empty = true }
21 | },
22 | [10] = {
23 | [1] = {
24 | ["name"] = "Great Stamina",
25 | ["rank"] = 1,
26 | ["cost"] = 10,
27 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
28 | ["id"] = 4187
29 | },
30 | [2] = {
31 | ["name"] = "Growl",
32 | ["rank"] = 2,
33 | ["cost"] = 0,
34 | ["texture"] = "Interface/ICONS/ability_physical_taunt",
35 | ["id"] = 14916
36 | },
37 | [3] = {
38 | ["name"] = "Natural Armor",
39 | ["rank"] = 1,
40 | ["cost"] = 10,
41 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
42 | ["id"] = 24545
43 | },
44 | },
45 | [12] = {
46 | [1] = {
47 | ["name"] = "Great Stamina",
48 | ["rank"] = 2,
49 | ["cost"] = 120,
50 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
51 | ["id"] = 4188
52 | },
53 | [2] = {
54 | ["name"] = "Natural Armor",
55 | ["rank"] = 2,
56 | ["cost"] = 120,
57 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
58 | ["id"] = 24549
59 | },
60 | },
61 | [14] = {
62 | { empty = true }
63 | },
64 | [16] = {
65 | { empty = true }
66 | },
67 | [18] = {
68 | [1] = {
69 | ["name"] = "Great Stamina",
70 | ["rank"] = 3,
71 | ["cost"] = 400,
72 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
73 | ["id"] = 4189
74 | },
75 | [2] = {
76 | ["name"] = "Natural Armor",
77 | ["rank"] = 3,
78 | ["cost"] = 400,
79 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
80 | ["id"] = 24550
81 | },
82 | },
83 | [20] = {
84 | [1] = {
85 | ["name"] = "Arcane Resistance",
86 | ["rank"] = 1,
87 | ["cost"] = 440,
88 | ["texture"] = "Interface/ICONS/spell_nature_starfall",
89 | ["id"] = 24493
90 | },
91 | [2] = {
92 | ["name"] = "Fire Resistance",
93 | ["rank"] = 1,
94 | ["cost"] = 440,
95 | ["texture"] = "Interface/ICONS/spell_fire_firearmor",
96 | ["id"] = 23992
97 | },
98 | [3] = {
99 | ["name"] = "Frost Resistance",
100 | ["rank"] = 1,
101 | ["cost"] = 440,
102 | ["texture"] = "Interface/ICONS/spell_frost_frostward",
103 | ["id"] = 24446
104 | },
105 | [4] = {
106 | ["name"] = "Growl",
107 | ["rank"] = 3,
108 | ["cost"] = 440,
109 | ["texture"] = "Interface/ICONS/ability_physical_taunt",
110 | ["id"] = 14917
111 | },
112 | [5] = {
113 | ["name"] = "Nature Resistance",
114 | ["rank"] = 1,
115 | ["cost"] = 440,
116 | ["texture"] = "Interface/ICONS/spell_nature_resistnature",
117 | ["id"] = 24492
118 | },
119 | [6] = {
120 | ["name"] = "Shadow Resistance",
121 | ["rank"] = 1,
122 | ["cost"] = 440,
123 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
124 | ["id"] = 24488
125 | },
126 | },
127 | [22] = {
128 | { empty = true }
129 | },
130 | [24] = {
131 | [1] = {
132 | ["name"] = "Great Stamina",
133 | ["rank"] = 4,
134 | ["cost"] = 1260,
135 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
136 | ["id"] = 4190
137 | },
138 | [2] = {
139 | ["name"] = "Natural Armor",
140 | ["rank"] = 4,
141 | ["cost"] = 1260,
142 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
143 | ["id"] = 24551
144 | },
145 | },
146 | [26] = {
147 | { empty = true }
148 | },
149 | [28] = {
150 | { empty = true }
151 | },
152 | [30] = {
153 | [1] = {
154 | ["name"] = "Arcane Resistance",
155 | ["rank"] = 2,
156 | ["cost"] = 1440,
157 | ["texture"] = "Interface/ICONS/spell_nature_starfall",
158 | ["id"] = 24497
159 | },
160 | [2] = {
161 | ["name"] = "Fire Resistance",
162 | ["rank"] = 2,
163 | ["cost"] = 1440,
164 | ["texture"] = "Interface/ICONS/spell_fire_firearmor",
165 | ["id"] = 24439
166 | },
167 | [3] = {
168 | ["name"] = "Frost Resistance",
169 | ["rank"] = 2,
170 | ["cost"] = 1440,
171 | ["texture"] = "Interface/ICONS/spell_frost_frostward",
172 | ["id"] = 24447
173 | },
174 | [4] = {
175 | ["name"] = "Great Stamina",
176 | ["rank"] = 5,
177 | ["cost"] = 1440,
178 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
179 | ["id"] = 4191
180 | },
181 | [5] = {
182 | ["name"] = "Growl",
183 | ["rank"] = 4,
184 | ["cost"] = 1440,
185 | ["texture"] = "Interface/ICONS/ability_physical_taunt",
186 | ["id"] = 14918
187 | },
188 | [6] = {
189 | ["name"] = "Natural Armor",
190 | ["rank"] = 5,
191 | ["cost"] = 1440,
192 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
193 | ["id"] = 24552
194 | },
195 | [7] = {
196 | ["name"] = "Nature Resistance",
197 | ["rank"] = 2,
198 | ["cost"] = 1440,
199 | ["texture"] = "Interface/ICONS/spell_nature_resistnature",
200 | ["id"] = 24502
201 | },
202 | [8] = {
203 | ["name"] = "Shadow Resistance",
204 | ["rank"] = 2,
205 | ["cost"] = 1440,
206 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
207 | ["id"] = 24505
208 | },
209 | },
210 | [32] = {
211 | { empty = true }
212 | },
213 | [34] = {
214 | { empty = true }
215 | },
216 | [36] = {
217 | [1] = {
218 | ["name"] = "Great Stamina",
219 | ["rank"] = 6,
220 | ["cost"] = 2520,
221 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
222 | ["id"] = 4192
223 | },
224 | [2] = {
225 | ["name"] = "Natural Armor",
226 | ["rank"] = 6,
227 | ["cost"] = 2520,
228 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
229 | ["id"] = 24553
230 | },
231 | },
232 | [38] = {
233 | { empty = true }
234 | },
235 | [40] = {
236 | [1] = {
237 | ["name"] = "Arcane Resistance",
238 | ["rank"] = 3,
239 | ["cost"] = 3240,
240 | ["texture"] = "Interface/ICONS/spell_nature_starfall",
241 | ["id"] = 24500
242 | },
243 | [2] = {
244 | ["name"] = "Fire Resistance",
245 | ["rank"] = 3,
246 | ["cost"] = 3240,
247 | ["texture"] = "Interface/ICONS/spell_fire_firearmor",
248 | ["id"] = 24444
249 | },
250 | [3] = {
251 | ["name"] = "Frost Resistance",
252 | ["rank"] = 3,
253 | ["cost"] = 3240,
254 | ["texture"] = "Interface/ICONS/spell_frost_frostward",
255 | ["id"] = 24448
256 | },
257 | [4] = {
258 | ["name"] = "Growl",
259 | ["rank"] = 5,
260 | ["cost"] = 3240,
261 | ["texture"] = "Interface/ICONS/ability_physical_taunt",
262 | ["id"] = 14919
263 | },
264 | [5] = {
265 | ["name"] = "Nature Resistance",
266 | ["rank"] = 3,
267 | ["cost"] = 3240,
268 | ["texture"] = "Interface/ICONS/spell_nature_resistnature",
269 | ["id"] = 24503
270 | },
271 | [6] = {
272 | ["name"] = "Shadow Resistance",
273 | ["rank"] = 3,
274 | ["cost"] = 3240,
275 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
276 | ["id"] = 24506
277 | },
278 | },
279 | [42] = {
280 | [1] = {
281 | ["name"] = "Great Stamina",
282 | ["rank"] = 7,
283 | ["cost"] = 4320,
284 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
285 | ["id"] = 4193
286 | },
287 | [2] = {
288 | ["name"] = "Natural Armor",
289 | ["rank"] = 7,
290 | ["cost"] = 4320,
291 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
292 | ["id"] = 24554
293 | },
294 | },
295 | [44] = {
296 | { empty = true }
297 | },
298 | [46] = {
299 | { empty = true }
300 | },
301 | [48] = {
302 | [1] = {
303 | ["name"] = "Great Stamina",
304 | ["rank"] = 8,
305 | ["cost"] = 5760,
306 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
307 | ["id"] = 4194
308 | },
309 | [2] = {
310 | ["name"] = "Natural Armor",
311 | ["rank"] = 8,
312 | ["cost"] = 5760,
313 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
314 | ["id"] = 24555
315 | },
316 | },
317 | [50] = {
318 | [1] = {
319 | ["name"] = "Arcane Resistance",
320 | ["rank"] = 4,
321 | ["cost"] = 6480,
322 | ["texture"] = "Interface/ICONS/spell_nature_starfall",
323 | ["id"] = 24501
324 | },
325 | [2] = {
326 | ["name"] = "Fire Resistance",
327 | ["rank"] = 4,
328 | ["cost"] = 6480,
329 | ["texture"] = "Interface/ICONS/spell_fire_firearmor",
330 | ["id"] = 24445
331 | },
332 | [3] = {
333 | ["name"] = "Frost Resistance",
334 | ["rank"] = 4,
335 | ["cost"] = 6480,
336 | ["texture"] = "Interface/ICONS/spell_frost_frostward",
337 | ["id"] = 24449
338 | },
339 | [4] = {
340 | ["name"] = "Growl",
341 | ["rank"] = 6,
342 | ["cost"] = 6480,
343 | ["texture"] = "Interface/ICONS/ability_physical_taunt",
344 | ["id"] = 14920
345 | },
346 | [5] = {
347 | ["name"] = "Nature Resistance",
348 | ["rank"] = 4,
349 | ["cost"] = 6480,
350 | ["texture"] = "Interface/ICONS/spell_nature_resistnature",
351 | ["id"] = 24504
352 | },
353 | [6] = {
354 | ["name"] = "Shadow Resistance",
355 | ["rank"] = 4,
356 | ["cost"] = 6480,
357 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
358 | ["id"] = 24507
359 | },
360 | },
361 | [52] = {
362 | { empty = true }
363 | },
364 | [54] = {
365 | [1] = {
366 | ["name"] = "Great Stamina",
367 | ["rank"] = 9,
368 | ["cost"] = 7560,
369 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
370 | ["id"] = 5041
371 | },
372 | [2] = {
373 | ["name"] = "Natural Armor",
374 | ["rank"] = 9,
375 | ["cost"] = 7560,
376 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
377 | ["id"] = 24629
378 | },
379 | },
380 | [56] = {
381 | { empty = true }
382 | },
383 | [58] = {
384 | { empty = true }
385 | },
386 | [60] = {
387 | [1] = {
388 | ["name"] = "Great Stamina",
389 | ["rank"] = 10,
390 | ["cost"] = 9000,
391 | ["texture"] = "Interface/ICONS/spell_nature_unyeildingstamina",
392 | ["id"] = 5042
393 | },
394 | [2] = {
395 | ["name"] = "Growl",
396 | ["rank"] = 7,
397 | ["cost"] = 9000,
398 | ["texture"] = "Interface/ICONS/ability_physical_taunt",
399 | ["id"] = 14921
400 | },
401 | [3] = {
402 | ["name"] = "Natural Armor",
403 | ["rank"] = 10,
404 | ["cost"] = 9000,
405 | ["texture"] = "Interface/ICONS/spell_nature_spiritarmor",
406 | ["id"] = 24630
407 | },
408 | },
409 | }
410 |
--------------------------------------------------------------------------------
/Database/Rogue.lua:
--------------------------------------------------------------------------------
1 | local _, FieldGuide = ...
2 |
3 | FieldGuide.ROGUE = {
4 | [2] = {
5 | [1] = {
6 | ["name"] = "Stealth",
7 | ["rank"] = 1,
8 | ["cost"] = 10,
9 | ["texture"] = "Interface/ICONS/ability_stealth",
10 | ["id"] = 1784
11 | },
12 | },
13 | [4] = {
14 | [1] = {
15 | ["name"] = "Backstab",
16 | ["rank"] = 1,
17 | ["cost"] = 100,
18 | ["texture"] = "Interface/ICONS/ability_backstab",
19 | ["id"] = 53
20 | },
21 | [2] = {
22 | ["name"] = "Pick Pocket",
23 | ["rank"] = 1,
24 | ["cost"] = 100,
25 | ["texture"] = "Interface/ICONS/inv_misc_bag_11",
26 | ["id"] = 921
27 | },
28 | },
29 | [6] = {
30 | [1] = {
31 | ["name"] = "Gouge",
32 | ["rank"] = 1,
33 | ["cost"] = 100,
34 | ["texture"] = "Interface/ICONS/ability_gouge",
35 | ["id"] = 1776
36 | },
37 | [2] = {
38 | ["name"] = "Sinister Strike",
39 | ["rank"] = 2,
40 | ["cost"] = 100,
41 | ["texture"] = "Interface/ICONS/spell_shadow_ritualofsacrifice",
42 | ["id"] = 1757
43 | },
44 | },
45 | [8] = {
46 | [1] = {
47 | ["name"] = "Eviscerate",
48 | ["rank"] = 2,
49 | ["cost"] = 200,
50 | ["texture"] = "Interface/ICONS/ability_rogue_eviscerate",
51 | ["id"] = 6760
52 | },
53 | [2] = {
54 | ["name"] = "Evasion",
55 | ["rank"] = 1,
56 | ["cost"] = 200,
57 | ["texture"] = "Interface/ICONS/spell_shadow_shadowward",
58 | ["id"] = 5277
59 | },
60 | },
61 | [10] = {
62 | [1] = {
63 | ["name"] = "Dual Wield",
64 | ["rank"] = 1,
65 | ["cost"] = 300,
66 | ["texture"] = "Interface/ICONS/ability_dualwield",
67 | ["id"] = 674
68 | },
69 | [2] = {
70 | ["name"] = "Slice and Dice",
71 | ["rank"] = 1,
72 | ["cost"] = 300,
73 | ["texture"] = "Interface/ICONS/ability_rogue_slicedice",
74 | ["id"] = 5171
75 | },
76 | [3] = {
77 | ["name"] = "Sprint",
78 | ["rank"] = 1,
79 | ["cost"] = 300,
80 | ["texture"] = "Interface/ICONS/ability_rogue_sprint",
81 | ["id"] = 2983
82 | },
83 | [4] = {
84 | ["name"] = "Sap",
85 | ["rank"] = 1,
86 | ["cost"] = 300,
87 | ["texture"] = "Interface/ICONS/ability_sap",
88 | ["id"] = 6770
89 | },
90 | },
91 | [12] = {
92 | [1] = {
93 | ["name"] = "Parry",
94 | ["rank"] = 1,
95 | ["cost"] = 800,
96 | ["texture"] = "Interface/ICONS/ability_parry",
97 | ["id"] = 3127
98 | },
99 | [2] = {
100 | ["name"] = "Backstab",
101 | ["rank"] = 2,
102 | ["cost"] = 800,
103 | ["texture"] = "Interface/ICONS/ability_backstab",
104 | ["id"] = 2589
105 | },
106 | [3] = {
107 | ["name"] = "Kick",
108 | ["rank"] = 1,
109 | ["cost"] = 800,
110 | ["texture"] = "Interface/ICONS/ability_kick",
111 | ["id"] = 1766
112 | },
113 | },
114 | [14] = {
115 | [1] = {
116 | ["name"] = "Expose Armor",
117 | ["rank"] = 1,
118 | ["cost"] = 1200,
119 | ["texture"] = "Interface/ICONS/ability_warrior_riposte",
120 | ["id"] = 8647
121 | },
122 | [2] = {
123 | ["name"] = "Garrote",
124 | ["rank"] = 1,
125 | ["cost"] = 1200,
126 | ["texture"] = "Interface/ICONS/ability_rogue_garrote",
127 | ["id"] = 703
128 | },
129 | [3] = {
130 | ["name"] = "Sinister Strike",
131 | ["rank"] = 3,
132 | ["cost"] = 1200,
133 | ["texture"] = "Interface/ICONS/spell_shadow_ritualofsacrifice",
134 | ["id"] = 1758
135 | },
136 | },
137 | [16] = {
138 | [1] = {
139 | ["name"] = "Pick Lock",
140 | ["rank"] = 1,
141 | ["cost"] = 1800,
142 | ["texture"] = "Interface/ICONS/spell_nature_moonkey",
143 | ["id"] = 1804
144 | },
145 | [2] = {
146 | ["name"] = "Eviscerate",
147 | ["rank"] = 3,
148 | ["cost"] = 1800,
149 | ["texture"] = "Interface/ICONS/ability_rogue_eviscerate",
150 | ["id"] = 6761
151 | },
152 | [3] = {
153 | ["name"] = "Feint",
154 | ["rank"] = 1,
155 | ["cost"] = 1800,
156 | ["texture"] = "Interface/ICONS/ability_rogue_feint",
157 | ["id"] = 1966
158 | },
159 | },
160 | [18] = {
161 | [1] = {
162 | ["name"] = "Ambush",
163 | ["rank"] = 1,
164 | ["cost"] = 2900,
165 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
166 | ["id"] = 8676
167 | },
168 | [2] = {
169 | ["name"] = "Gouge",
170 | ["rank"] = 2,
171 | ["cost"] = 2900,
172 | ["texture"] = "Interface/ICONS/ability_gouge",
173 | ["id"] = 1777
174 | },
175 | },
176 | [20] = {
177 | [1] = {
178 | ["name"] = "Poisons",
179 | ["rank"] = 1,
180 | ["cost"] = 0,
181 | ["texture"] = "Interface/ICONS/trade_brewpoison",
182 | ["id"] = 2842
183 | },
184 | [2] = {
185 | ["name"] = "Crippling Poison",
186 | ["rank"] = 1,
187 | ["cost"] = 3000,
188 | ["texture"] = "Interface/ICONS/ability_poisonsting",
189 | ["id"] = 3420
190 | },
191 | [3] = {
192 | ["name"] = "Instant Poison",
193 | ["rank"] = 1,
194 | ["cost"] = 0,
195 | ["texture"] = "Interface/ICONS/ability_poisons",
196 | ["id"] = 8681
197 | },
198 | [4] = {
199 | ["name"] = "Rupture",
200 | ["rank"] = 1,
201 | ["cost"] = 3000,
202 | ["texture"] = "Interface/ICONS/ability_rogue_rupture",
203 | ["id"] = 1943
204 | },
205 | [5] = {
206 | ["name"] = "Backstab",
207 | ["rank"] = 3,
208 | ["cost"] = 3000,
209 | ["texture"] = "Interface/ICONS/ability_backstab",
210 | ["id"] = 2590
211 | },
212 | [6] = {
213 | ["name"] = "Stealth",
214 | ["rank"] = 2,
215 | ["cost"] = 3000,
216 | ["texture"] = "Interface/ICONS/ability_stealth",
217 | ["id"] = 1785
218 | },
219 | },
220 | [22] = {
221 | [1] = {
222 | ["name"] = "Garrote",
223 | ["rank"] = 2,
224 | ["cost"] = 4000,
225 | ["texture"] = "Interface/ICONS/ability_rogue_garrote",
226 | ["id"] = 8631
227 | },
228 | [2] = {
229 | ["name"] = "Sinister Strike",
230 | ["rank"] = 4,
231 | ["cost"] = 4000,
232 | ["texture"] = "Interface/ICONS/spell_shadow_ritualofsacrifice",
233 | ["id"] = 1759
234 | },
235 | [3] = {
236 | ["name"] = "Distract",
237 | ["rank"] = 1,
238 | ["cost"] = 4000,
239 | ["texture"] = "Interface/ICONS/ability_rogue_distract",
240 | ["id"] = 1725
241 | },
242 | [4] = {
243 | ["name"] = "Vanish",
244 | ["rank"] = 1,
245 | ["cost"] = 4000,
246 | ["texture"] = "Interface/ICONS/ability_vanish",
247 | ["id"] = 1856
248 | },
249 | },
250 | [24] = {
251 | [1] = {
252 | ["name"] = "Mind-numbing Poison",
253 | ["rank"] = 1,
254 | ["cost"] = 5000,
255 | ["texture"] = "Interface/ICONS/spell_nature_nullifydisease",
256 | ["id"] = 5763
257 | },
258 | [2] = {
259 | ["name"] = "Eviscerate",
260 | ["rank"] = 4,
261 | ["cost"] = 5000,
262 | ["texture"] = "Interface/ICONS/ability_rogue_eviscerate",
263 | ["id"] = 6762
264 | },
265 | [3] = {
266 | ["name"] = "Detect Traps",
267 | ["rank"] = 1,
268 | ["cost"] = 5000,
269 | ["texture"] = "Interface/ICONS/ability_spy",
270 | ["id"] = 2836
271 | },
272 | },
273 | [26] = {
274 | [1] = {
275 | ["name"] = "Ambush",
276 | ["rank"] = 2,
277 | ["cost"] = 6000,
278 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
279 | ["id"] = 8724
280 | },
281 | [2] = {
282 | ["name"] = "Cheap Shot",
283 | ["rank"] = 1,
284 | ["cost"] = 6000,
285 | ["texture"] = "Interface/ICONS/ability_cheapshot",
286 | ["id"] = 1833
287 | },
288 | [3] = {
289 | ["name"] = "Expose Armor",
290 | ["rank"] = 2,
291 | ["cost"] = 6000,
292 | ["texture"] = "Interface/ICONS/ability_warrior_riposte",
293 | ["id"] = 8649
294 | },
295 | [4] = {
296 | ["name"] = "Kick",
297 | ["rank"] = 2,
298 | ["cost"] = 6000,
299 | ["texture"] = "Interface/ICONS/ability_kick",
300 | ["id"] = 1767
301 | },
302 | },
303 | [28] = {
304 | [1] = {
305 | ["name"] = "Instant Poison II",
306 | ["rank"] = 2,
307 | ["cost"] = 8000,
308 | ["texture"] = "Interface/ICONS/ability_poisons",
309 | ["id"] = 8687
310 | },
311 | [2] = {
312 | ["name"] = "Rupture",
313 | ["rank"] = 2,
314 | ["cost"] = 8000,
315 | ["texture"] = "Interface/ICONS/ability_rogue_rupture",
316 | ["id"] = 8639
317 | },
318 | [3] = {
319 | ["name"] = "Backstab",
320 | ["rank"] = 4,
321 | ["cost"] = 8000,
322 | ["texture"] = "Interface/ICONS/ability_backstab",
323 | ["id"] = 2591
324 | },
325 | [4] = {
326 | ["name"] = "Feint",
327 | ["rank"] = 2,
328 | ["cost"] = 8000,
329 | ["texture"] = "Interface/ICONS/ability_rogue_feint",
330 | ["id"] = 6768
331 | },
332 | [5] = {
333 | ["name"] = "Sap",
334 | ["rank"] = 2,
335 | ["cost"] = 8000,
336 | ["texture"] = "Interface/ICONS/ability_sap",
337 | ["id"] = 2070
338 | },
339 | },
340 | [30] = {
341 | [1] = {
342 | ["name"] = "Deadly Poison",
343 | ["rank"] = 1,
344 | ["cost"] = 10000,
345 | ["texture"] = "Interface/ICONS/ability_rogue_dualweild",
346 | ["id"] = 2835
347 | },
348 | [2] = {
349 | ["name"] = "Garrote",
350 | ["rank"] = 3,
351 | ["cost"] = 10000,
352 | ["texture"] = "Interface/ICONS/ability_rogue_garrote",
353 | ["id"] = 8632
354 | },
355 | [3] = {
356 | ["name"] = "Kidney Shot",
357 | ["rank"] = 1,
358 | ["cost"] = 10000,
359 | ["texture"] = "Interface/ICONS/ability_rogue_kidneyshot",
360 | ["id"] = 408
361 | },
362 | [4] = {
363 | ["name"] = "Sinister Strike",
364 | ["rank"] = 5,
365 | ["cost"] = 10000,
366 | ["texture"] = "Interface/ICONS/spell_shadow_ritualofsacrifice",
367 | ["id"] = 1760
368 | },
369 | [5] = {
370 | ["name"] = "Disarm Trap",
371 | ["rank"] = 1,
372 | ["cost"] = 10000,
373 | ["texture"] = "Interface/ICONS/spell_shadow_grimward",
374 | ["id"] = 1842
375 | },
376 | },
377 | [32] = {
378 | [1] = {
379 | ["name"] = "Wound Poison",
380 | ["rank"] = 1,
381 | ["cost"] = 12000,
382 | ["texture"] = "Interface/ICONS/ability_poisonsting",
383 | ["id"] = 13220
384 | },
385 | [2] = {
386 | ["name"] = "Eviscerate",
387 | ["rank"] = 5,
388 | ["cost"] = 12000,
389 | ["texture"] = "Interface/ICONS/ability_rogue_eviscerate",
390 | ["id"] = 8623
391 | },
392 | [3] = {
393 | ["name"] = "Gouge",
394 | ["rank"] = 3,
395 | ["cost"] = 12000,
396 | ["texture"] = "Interface/ICONS/ability_gouge",
397 | ["id"] = 8629
398 | },
399 | },
400 | [34] = {
401 | [1] = {
402 | ["name"] = "Blinding Powder",
403 | ["rank"] = 1,
404 | ["cost"] = 14000,
405 | ["texture"] = "Interface/ICONS/inv_misc_ammo_gunpowder_01",
406 | ["id"] = 6510
407 | },
408 | [2] = {
409 | ["name"] = "Ambush",
410 | ["rank"] = 3,
411 | ["cost"] = 14000,
412 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
413 | ["id"] = 8725
414 | },
415 | [3] = {
416 | ["name"] = "Sprint",
417 | ["rank"] = 2,
418 | ["cost"] = 14000,
419 | ["texture"] = "Interface/ICONS/ability_rogue_sprint",
420 | ["id"] = 8696
421 | },
422 | [4] = {
423 | ["name"] = "Blind",
424 | ["rank"] = 1,
425 | ["cost"] = 14000,
426 | ["texture"] = "Interface/ICONS/spell_shadow_mindsteal",
427 | ["id"] = 2094
428 | },
429 | },
430 | [36] = {
431 | [1] = {
432 | ["name"] = "Instant Poison III",
433 | ["rank"] = 3,
434 | ["cost"] = 16000,
435 | ["texture"] = "Interface/ICONS/ability_poisons",
436 | ["id"] = 8691
437 | },
438 | [2] = {
439 | ["name"] = "Expose Armor",
440 | ["rank"] = 3,
441 | ["cost"] = 16000,
442 | ["texture"] = "Interface/ICONS/ability_warrior_riposte",
443 | ["id"] = 8650
444 | },
445 | [3] = {
446 | ["name"] = "Rupture",
447 | ["rank"] = 3,
448 | ["cost"] = 16000,
449 | ["texture"] = "Interface/ICONS/ability_rogue_rupture",
450 | ["id"] = 8640
451 | },
452 | [4] = {
453 | ["name"] = "Backstab",
454 | ["rank"] = 5,
455 | ["cost"] = 16000,
456 | ["texture"] = "Interface/ICONS/ability_backstab",
457 | ["id"] = 8721
458 | },
459 | },
460 | [38] = {
461 | [1] = {
462 | ["name"] = "Mind-numbing Poison II",
463 | ["rank"] = 2,
464 | ["cost"] = 18000,
465 | ["texture"] = "Interface/ICONS/spell_nature_nullifydisease",
466 | ["id"] = 8694
467 | },
468 | [2] = {
469 | ["name"] = "Deadly Poison II",
470 | ["rank"] = 2,
471 | ["cost"] = 18000,
472 | ["texture"] = "Interface/ICONS/ability_rogue_dualweild",
473 | ["id"] = 2837
474 | },
475 | [3] = {
476 | ["name"] = "Garrote",
477 | ["rank"] = 4,
478 | ["cost"] = 18000,
479 | ["texture"] = "Interface/ICONS/ability_rogue_garrote",
480 | ["id"] = 8633
481 | },
482 | [4] = {
483 | ["name"] = "Sinister Strike",
484 | ["rank"] = 6,
485 | ["cost"] = 18000,
486 | ["texture"] = "Interface/ICONS/spell_shadow_ritualofsacrifice",
487 | ["id"] = 8621
488 | },
489 | },
490 | [40] = {
491 | [1] = {
492 | ["name"] = "Wound Poison II",
493 | ["rank"] = 2,
494 | ["cost"] = 20000,
495 | ["texture"] = "Interface/ICONS/ability_poisonsting",
496 | ["id"] = 13228
497 | },
498 | [2] = {
499 | ["name"] = "Eviscerate",
500 | ["rank"] = 6,
501 | ["cost"] = 20000,
502 | ["texture"] = "Interface/ICONS/ability_rogue_eviscerate",
503 | ["id"] = 8624
504 | },
505 | [3] = {
506 | ["name"] = "Feint",
507 | ["rank"] = 3,
508 | ["cost"] = 20000,
509 | ["texture"] = "Interface/ICONS/ability_rogue_feint",
510 | ["id"] = 8637
511 | },
512 | [4] = {
513 | ["name"] = "Safe Fall",
514 | ["rank"] = 1,
515 | ["cost"] = 0,
516 | ["texture"] = "Interface/ICONS/inv_feather_01",
517 | ["id"] = 1860
518 | },
519 | [5] = {
520 | ["name"] = "Stealth",
521 | ["rank"] = 3,
522 | ["cost"] = 20000,
523 | ["texture"] = "Interface/ICONS/ability_stealth",
524 | ["id"] = 1786
525 | },
526 | },
527 | [42] = {
528 | [1] = {
529 | ["name"] = "Ambush",
530 | ["rank"] = 4,
531 | ["cost"] = 27000,
532 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
533 | ["id"] = 11267
534 | },
535 | [2] = {
536 | ["name"] = "Slice and Dice",
537 | ["rank"] = 2,
538 | ["cost"] = 27000,
539 | ["texture"] = "Interface/ICONS/ability_rogue_slicedice",
540 | ["id"] = 6774
541 | },
542 | [3] = {
543 | ["name"] = "Kick",
544 | ["rank"] = 3,
545 | ["cost"] = 27000,
546 | ["texture"] = "Interface/ICONS/ability_kick",
547 | ["id"] = 1768
548 | },
549 | [4] = {
550 | ["name"] = "Vanish",
551 | ["rank"] = 2,
552 | ["cost"] = 27000,
553 | ["texture"] = "Interface/ICONS/ability_vanish",
554 | ["id"] = 1857
555 | },
556 | },
557 | [44] = {
558 | [1] = {
559 | ["name"] = "Instant Poison IV",
560 | ["rank"] = 4,
561 | ["cost"] = 29000,
562 | ["texture"] = "Interface/ICONS/ability_poisons",
563 | ["id"] = 11341
564 | },
565 | [2] = {
566 | ["name"] = "Rupture",
567 | ["rank"] = 4,
568 | ["cost"] = 29000,
569 | ["texture"] = "Interface/ICONS/ability_rogue_rupture",
570 | ["id"] = 11273
571 | },
572 | [3] = {
573 | ["name"] = "Backstab",
574 | ["rank"] = 6,
575 | ["cost"] = 29000,
576 | ["texture"] = "Interface/ICONS/ability_backstab",
577 | ["id"] = 11279
578 | },
579 | },
580 | [46] = {
581 | [1] = {
582 | ["name"] = "Deadly Poison III",
583 | ["rank"] = 3,
584 | ["cost"] = 31000,
585 | ["texture"] = "Interface/ICONS/ability_rogue_dualweild",
586 | ["id"] = 11357
587 | },
588 | [2] = {
589 | ["name"] = "Expose Armor",
590 | ["rank"] = 4,
591 | ["cost"] = 31000,
592 | ["texture"] = "Interface/ICONS/ability_warrior_riposte",
593 | ["id"] = 11197
594 | },
595 | [3] = {
596 | ["name"] = "Garrote",
597 | ["rank"] = 5,
598 | ["cost"] = 31000,
599 | ["texture"] = "Interface/ICONS/ability_rogue_garrote",
600 | ["id"] = 11289
601 | },
602 | [4] = {
603 | ["name"] = "Gouge",
604 | ["rank"] = 4,
605 | ["cost"] = 31000,
606 | ["texture"] = "Interface/ICONS/ability_gouge",
607 | ["id"] = 11285
608 | },
609 | [5] = {
610 | ["name"] = "Sinister Strike",
611 | ["rank"] = 7,
612 | ["cost"] = 31000,
613 | ["texture"] = "Interface/ICONS/spell_shadow_ritualofsacrifice",
614 | ["id"] = 11293
615 | },
616 | [6] = {
617 | ["name"] = "Hemorrhage",
618 | ["rank"] = 2,
619 | ["cost"] = 7750,
620 | ["texture"] = "Interface/ICONS/spell_shadow_lifedrain",
621 | ["id"] = 17347,
622 | ["talent"] = true
623 | },
624 | },
625 | [48] = {
626 | [1] = {
627 | ["name"] = "Wound Poison III",
628 | ["rank"] = 3,
629 | ["cost"] = 33000,
630 | ["texture"] = "Interface/ICONS/ability_poisonsting",
631 | ["id"] = 13229
632 | },
633 | [2] = {
634 | ["name"] = "Eviscerate",
635 | ["rank"] = 7,
636 | ["cost"] = 33000,
637 | ["texture"] = "Interface/ICONS/ability_rogue_eviscerate",
638 | ["id"] = 11299
639 | },
640 | [3] = {
641 | ["name"] = "Sap",
642 | ["rank"] = 3,
643 | ["cost"] = 33000,
644 | ["texture"] = "Interface/ICONS/ability_sap",
645 | ["id"] = 11297
646 | },
647 | },
648 | [50] = {
649 | [1] = {
650 | ["name"] = "Crippling Poison II",
651 | ["rank"] = 2,
652 | ["cost"] = 35000,
653 | ["texture"] = "Interface/ICONS/inv_potion_19",
654 | ["id"] = 3421
655 | },
656 | [2] = {
657 | ["name"] = "Ambush",
658 | ["rank"] = 5,
659 | ["cost"] = 35000,
660 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
661 | ["id"] = 11268
662 | },
663 | [3] = {
664 | ["name"] = "Kidney Shot",
665 | ["rank"] = 2,
666 | ["cost"] = 35000,
667 | ["texture"] = "Interface/ICONS/ability_rogue_kidneyshot",
668 | ["id"] = 8643
669 | },
670 | },
671 | [52] = {
672 | [1] = {
673 | ["name"] = "Mind-numbing Poison III",
674 | ["rank"] = 3,
675 | ["cost"] = 46000,
676 | ["texture"] = "Interface/ICONS/spell_nature_nullifydisease",
677 | ["id"] = 11400
678 | },
679 | [2] = {
680 | ["name"] = "Instant Poison V",
681 | ["rank"] = 5,
682 | ["cost"] = 46000,
683 | ["texture"] = "Interface/ICONS/ability_poisons",
684 | ["id"] = 11342
685 | },
686 | [3] = {
687 | ["name"] = "Rupture",
688 | ["rank"] = 5,
689 | ["cost"] = 46000,
690 | ["texture"] = "Interface/ICONS/ability_rogue_rupture",
691 | ["id"] = 11274
692 | },
693 | [4] = {
694 | ["name"] = "Backstab",
695 | ["rank"] = 7,
696 | ["cost"] = 46000,
697 | ["texture"] = "Interface/ICONS/ability_backstab",
698 | ["id"] = 11280
699 | },
700 | [5] = {
701 | ["name"] = "Feint",
702 | ["rank"] = 4,
703 | ["cost"] = 46000,
704 | ["texture"] = "Interface/ICONS/ability_rogue_feint",
705 | ["id"] = 11303
706 | },
707 | },
708 | [54] = {
709 | [1] = {
710 | ["name"] = "Deadly Poison IV",
711 | ["rank"] = 4,
712 | ["cost"] = 48000,
713 | ["texture"] = "Interface/ICONS/ability_rogue_dualweild",
714 | ["id"] = 11358
715 | },
716 | [2] = {
717 | ["name"] = "Garrote",
718 | ["rank"] = 6,
719 | ["cost"] = 48000,
720 | ["texture"] = "Interface/ICONS/ability_rogue_garrote",
721 | ["id"] = 11290
722 | },
723 | [3] = {
724 | ["name"] = "Sinister Strike",
725 | ["rank"] = 8,
726 | ["cost"] = 48000,
727 | ["texture"] = "Interface/ICONS/spell_shadow_ritualofsacrifice",
728 | ["id"] = 11294
729 | },
730 | },
731 | [56] = {
732 | [1] = {
733 | ["name"] = "Wound Poison IV",
734 | ["rank"] = 4,
735 | ["cost"] = 50000,
736 | ["texture"] = "Interface/ICONS/ability_poisonsting",
737 | ["id"] = 13230
738 | },
739 | [2] = {
740 | ["name"] = "Eviscerate",
741 | ["rank"] = 8,
742 | ["cost"] = 50000,
743 | ["texture"] = "Interface/ICONS/ability_rogue_eviscerate",
744 | ["id"] = 11300
745 | },
746 | [3] = {
747 | ["name"] = "Expose Armor",
748 | ["rank"] = 5,
749 | ["cost"] = 50000,
750 | ["texture"] = "Interface/ICONS/ability_warrior_riposte",
751 | ["id"] = 11198
752 | },
753 | },
754 | [58] = {
755 | [1] = {
756 | ["name"] = "Ambush",
757 | ["rank"] = 6,
758 | ["cost"] = 52000,
759 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
760 | ["id"] = 11269
761 | },
762 | [2] = {
763 | ["name"] = "Kick",
764 | ["rank"] = 4,
765 | ["cost"] = 52000,
766 | ["texture"] = "Interface/ICONS/ability_kick",
767 | ["id"] = 1769
768 | },
769 | [3] = {
770 | ["name"] = "Sprint",
771 | ["rank"] = 3,
772 | ["cost"] = 52000,
773 | ["texture"] = "Interface/ICONS/ability_rogue_sprint",
774 | ["id"] = 11305
775 | },
776 | [4] = {
777 | ["name"] = "Hemorrhage",
778 | ["rank"] = 3,
779 | ["cost"] = 13000,
780 | ["texture"] = "Interface/ICONS/spell_shadow_lifedrain",
781 | ["id"] = 17348,
782 | ["talent"] = true
783 | },
784 | },
785 | [60] = {
786 | [1] = {
787 | ["name"] = "Instant Poison VI",
788 | ["rank"] = 6,
789 | ["cost"] = 54000,
790 | ["texture"] = "Interface/ICONS/ability_poisons",
791 | ["id"] = 11343
792 | },
793 | [2] = {
794 | ["name"] = "Rupture",
795 | ["rank"] = 6,
796 | ["cost"] = 54000,
797 | ["texture"] = "Interface/ICONS/ability_rogue_rupture",
798 | ["id"] = 11275
799 | },
800 | [3] = {
801 | ["name"] = "Backstab",
802 | ["rank"] = 8,
803 | ["cost"] = 54000,
804 | ["texture"] = "Interface/ICONS/ability_backstab",
805 | ["id"] = 11281
806 | },
807 | [4] = {
808 | ["name"] = "Gouge",
809 | ["rank"] = 5,
810 | ["cost"] = 54000,
811 | ["texture"] = "Interface/ICONS/ability_gouge",
812 | ["id"] = 11286
813 | },
814 | [5] = {
815 | ["name"] = "Stealth",
816 | ["rank"] = 4,
817 | ["cost"] = 54000,
818 | ["texture"] = "Interface/ICONS/ability_stealth",
819 | ["id"] = 1787
820 | },
821 | },
822 | }
823 |
--------------------------------------------------------------------------------
/Database/WarlockPets.lua:
--------------------------------------------------------------------------------
1 | local _, FieldGuide = ...
2 |
3 | FieldGuide.WARLOCK_PETS = {
4 | [2] = {
5 | { empty = true } -- No spells at this level.
6 | },
7 | [4] = {
8 | [1] = {
9 | ["name"] = "Blood Pact",
10 | ["rank"] = 1,
11 | ["cost"] = 100,
12 | ["texture"] = "Interface/ICONS/spell_shadow_bloodboil",
13 | ["id"] = 6307
14 | },
15 | },
16 | [6] = {
17 | { empty = true }
18 | },
19 | [8] = {
20 | [1] = {
21 | ["name"] = "Firebolt",
22 | ["rank"] = 2,
23 | ["cost"] = 100,
24 | ["texture"] = "Interface/ICONS/spell_fire_firebolt",
25 | ["id"] = 7799
26 | },
27 | },
28 | [10] = {
29 | { empty = true }
30 | },
31 | [12] = {
32 | [1] = {
33 | ["name"] = "Phase Shift",
34 | ["rank"] = 1,
35 | ["cost"] = 600,
36 | ["texture"] = "Interface/ICONS/spell_shadow_impphaseshift",
37 | ["id"] = 4511
38 | },
39 | },
40 | [14] = {
41 | [1] = {
42 | ["name"] = "Blood Pact",
43 | ["rank"] = 2,
44 | ["cost"] = 900,
45 | ["texture"] = "Interface/ICONS/spell_shadow_bloodboil",
46 | ["id"] = 7804
47 | },
48 | [2] = {
49 | ["name"] = "Fire Shield",
50 | ["rank"] = 1,
51 | ["cost"] = 900,
52 | ["texture"] = "Interface/ICONS/spell_fire_firearmor",
53 | ["id"] = 2947
54 | },
55 | },
56 | [16] = {
57 | [1] = {
58 | ["name"] = "Sacrifice",
59 | ["rank"] = 1,
60 | ["cost"] = 1200,
61 | ["texture"] = "Interface/ICONS/spell_shadow_sacrificialshield",
62 | ["id"] = 7812
63 | },
64 | },
65 | [18] = {
66 | [1] = {
67 | ["name"] = "Consume Shadows",
68 | ["rank"] = 1,
69 | ["cost"] = 1500,
70 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
71 | ["id"] = 17767
72 | },
73 | [2] = {
74 | ["name"] = "Firebolt",
75 | ["rank"] = 3,
76 | ["cost"] = 1500,
77 | ["texture"] = "Interface/ICONS/spell_fire_firebolt",
78 | ["id"] = 7800
79 | },
80 | },
81 | [20] = {
82 | [1] = {
83 | ["name"] = "Torment",
84 | ["rank"] = 2,
85 | ["cost"] = 2000,
86 | ["texture"] = "Interface/ICONS/spell_shadow_gathershadows",
87 | ["id"] = 7809
88 | },
89 | },
90 | [22] = {
91 | [1] = {
92 | ["name"] = "Soothing Kiss",
93 | ["rank"] = 1,
94 | ["cost"] = 2500,
95 | ["texture"] = "Interface/ICONS/spell_shadow_soothingkiss",
96 | ["id"] = 6360
97 | },
98 | },
99 | [24] = {
100 | [1] = {
101 | ["name"] = "Fire Shield",
102 | ["rank"] = 2,
103 | ["cost"] = 3000,
104 | ["texture"] = "Interface/ICONS/spell_fire_firearmor",
105 | ["id"] = 8316
106 | },
107 | [2] = {
108 | ["name"] = "Sacrifice",
109 | ["rank"] = 2,
110 | ["cost"] = 3000,
111 | ["texture"] = "Interface/ICONS/spell_shadow_sacrificialshield",
112 | ["id"] = 19438
113 | },
114 | [3] = {
115 | ["name"] = "Suffering",
116 | ["rank"] = 1,
117 | ["cost"] = 3000,
118 | ["texture"] = "Interface/ICONS/spell_shadow_blackplague",
119 | ["id"] = 17735
120 | },
121 | },
122 | [26] = {
123 | [1] = {
124 | ["name"] = "Blood Pact",
125 | ["rank"] = 3,
126 | ["cost"] = 4000,
127 | ["texture"] = "Interface/ICONS/spell_shadow_bloodboil",
128 | ["id"] = 7805
129 | },
130 | [2] = {
131 | ["name"] = "Consume Shadows",
132 | ["rank"] = 2,
133 | ["cost"] = 4000,
134 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
135 | ["id"] = 17850
136 | },
137 | [3] = {
138 | ["name"] = "Seduction",
139 | ["rank"] = 1,
140 | ["cost"] = 4000,
141 | ["texture"] = "Interface/ICONS/spell_shadow_mindsteal",
142 | ["id"] = 6358
143 | },
144 | },
145 | [28] = {
146 | [1] = {
147 | ["name"] = "Firebolt",
148 | ["rank"] = 4,
149 | ["cost"] = 5000,
150 | ["texture"] = "Interface/ICONS/spell_fire_firebolt",
151 | ["id"] = 7801
152 | },
153 | [2] = {
154 | ["name"] = "Lash of Pain",
155 | ["rank"] = 2,
156 | ["cost"] = 5000,
157 | ["texture"] = "Interface/ICONS/spell_shadow_curse",
158 | ["id"] = 7815
159 | },
160 | },
161 | [30] = {
162 | [1] = {
163 | ["name"] = "Torment",
164 | ["rank"] = 3,
165 | ["cost"] = 6000,
166 | ["texture"] = "Interface/ICONS/spell_shadow_gathershadows",
167 | ["id"] = 7810
168 | },
169 | },
170 | [32] = {
171 | [1] = {
172 | ["name"] = "Lesser Invisibility",
173 | ["rank"] = 1,
174 | ["cost"] = 7000,
175 | ["texture"] = "Interface/ICONS/spell_magic_lesserinvisibilty",
176 | ["id"] = 7870
177 | },
178 | [2] = {
179 | ["name"] = "Sacrifice",
180 | ["rank"] = 3,
181 | ["cost"] = 7000,
182 | ["texture"] = "Interface/ICONS/spell_shadow_sacrificialshield",
183 | ["id"] = 19440
184 | },
185 | [3] = {
186 | ["name"] = "Tainted Blood",
187 | ["rank"] = 1,
188 | ["cost"] = 7000,
189 | ["texture"] = "Interface/ICONS/spell_shadow_lifedrain",
190 | ["id"] = 19478
191 | },
192 | },
193 | [34] = {
194 | [1] = {
195 | ["name"] = "Consume Shadows",
196 | ["rank"] = 3,
197 | ["cost"] = 8000,
198 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
199 | ["id"] = 17851
200 | },
201 | [2] = {
202 | ["name"] = "Fire Shield",
203 | ["rank"] = 3,
204 | ["cost"] = 8000,
205 | ["texture"] = "Interface/ICONS/spell_fire_firearmor",
206 | ["id"] = 8317
207 | },
208 | [3] = {
209 | ["name"] = "Soothing Kiss",
210 | ["rank"] = 2,
211 | ["cost"] = 8000,
212 | ["texture"] = "Interface/ICONS/spell_shadow_soothingkiss",
213 | ["id"] = 7813
214 | },
215 | },
216 | [36] = {
217 | [1] = {
218 | ["name"] = "Lash of Pain",
219 | ["rank"] = 3,
220 | ["cost"] = 9000,
221 | ["texture"] = "Interface/ICONS/spell_shadow_curse",
222 | ["id"] = 7816
223 | },
224 | [2] = {
225 | ["name"] = "Spell Lock",
226 | ["rank"] = 1,
227 | ["cost"] = 9000,
228 | ["texture"] = "Interface/ICONS/spell_shadow_mindrot",
229 | ["id"] = 19244
230 | },
231 | [3] = {
232 | ["name"] = "Suffering",
233 | ["rank"] = 2,
234 | ["cost"] = 9000,
235 | ["texture"] = "Interface/ICONS/spell_shadow_blackplague",
236 | ["id"] = 17750
237 | },
238 | },
239 | [38] = {
240 | [1] = {
241 | ["name"] = "Blood Pact",
242 | ["rank"] = 4,
243 | ["cost"] = 10000,
244 | ["texture"] = "Interface/ICONS/spell_shadow_bloodboil",
245 | ["id"] = 11766
246 | },
247 | [2] = {
248 | ["name"] = "Devour Magic",
249 | ["rank"] = 2,
250 | ["cost"] = 10000,
251 | ["texture"] = "Interface/ICONS/spell_nature_purge",
252 | ["id"] = 19731
253 | },
254 | [3] = {
255 | ["name"] = "Firebolt",
256 | ["rank"] = 5,
257 | ["cost"] = 10000,
258 | ["texture"] = "Interface/ICONS/spell_fire_firebolt",
259 | ["id"] = 7802
260 | },
261 | },
262 | [40] = {
263 | [1] = {
264 | ["name"] = "Sacrifice",
265 | ["rank"] = 4,
266 | ["cost"] = 11000,
267 | ["texture"] = "Interface/ICONS/spell_shadow_sacrificialshield",
268 | ["id"] = 19441
269 | },
270 | [2] = {
271 | ["name"] = "Tainted Blood",
272 | ["rank"] = 2,
273 | ["cost"] = 11000,
274 | ["texture"] = "Interface/ICONS/spell_shadow_lifedrain",
275 | ["id"] = 19655
276 | },
277 | [3] = {
278 | ["name"] = "Torment",
279 | ["rank"] = 4,
280 | ["cost"] = 11000,
281 | ["texture"] = "Interface/ICONS/spell_shadow_gathershadows",
282 | ["id"] = 7811
283 | },
284 | },
285 | [42] = {
286 | [1] = {
287 | ["name"] = "Consume Shadows",
288 | ["rank"] = 4,
289 | ["cost"] = 11000,
290 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
291 | ["id"] = 17852
292 | },
293 | [2] = {
294 | ["name"] = "Paranoia",
295 | ["rank"] = 1,
296 | ["cost"] = 11000,
297 | ["texture"] = "Interface/ICONS/spell_shadow_auraofdarkness",
298 | ["id"] = 19480
299 | },
300 | },
301 | [44] = {
302 | [1] = {
303 | ["name"] = "Fire Shield",
304 | ["rank"] = 4,
305 | ["cost"] = 12000,
306 | ["texture"] = "Interface/ICONS/spell_fire_firearmor",
307 | ["id"] = 16329
308 | },
309 | [2] = {
310 | ["name"] = "Lash of Pain",
311 | ["rank"] = 4,
312 | ["cost"] = 12000,
313 | ["texture"] = "Interface/ICONS/spell_shadow_curse",
314 | ["id"] = 11778
315 | },
316 | },
317 | [46] = {
318 | [1] = {
319 | ["name"] = "Devour Magic",
320 | ["rank"] = 3,
321 | ["cost"] = 13000,
322 | ["texture"] = "Interface/ICONS/spell_nature_purge",
323 | ["id"] = 19734
324 | },
325 | [2] = {
326 | ["name"] = "Soothing Kiss",
327 | ["rank"] = 3,
328 | ["cost"] = 13000,
329 | ["texture"] = "Interface/ICONS/spell_shadow_soothingkiss",
330 | ["id"] = 11784
331 | },
332 | },
333 | [48] = {
334 | [1] = {
335 | ["name"] = "Firebolt",
336 | ["rank"] = 6,
337 | ["cost"] = 14000,
338 | ["texture"] = "Interface/ICONS/spell_fire_firebolt",
339 | ["id"] = 11762
340 | },
341 | [2] = {
342 | ["name"] = "Sacrifice",
343 | ["rank"] = 5,
344 | ["cost"] = 14000,
345 | ["texture"] = "Interface/ICONS/spell_shadow_sacrificialshield",
346 | ["id"] = 19442
347 | },
348 | [3] = {
349 | ["name"] = "Suffering",
350 | ["rank"] = 3,
351 | ["cost"] = 14000,
352 | ["texture"] = "Interface/ICONS/spell_shadow_blackplague",
353 | ["id"] = 17751
354 | },
355 | [4] = {
356 | ["name"] = "Tainted Blood",
357 | ["rank"] = 3,
358 | ["cost"] = 14000,
359 | ["texture"] = "Interface/ICONS/spell_shadow_lifedrain",
360 | ["id"] = 19656
361 | },
362 | },
363 | [50] = {
364 | [1] = {
365 | ["name"] = "Blood Pact",
366 | ["rank"] = 5,
367 | ["cost"] = 15000,
368 | ["texture"] = "Interface/ICONS/spell_shadow_bloodboil",
369 | ["id"] = 11767
370 | },
371 | [2] = {
372 | ["name"] = "Consume Shadows",
373 | ["rank"] = 5,
374 | ["cost"] = 15000,
375 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
376 | ["id"] = 17853
377 | },
378 | [3] = {
379 | ["name"] = "Torment",
380 | ["rank"] = 5,
381 | ["cost"] = 15000,
382 | ["texture"] = "Interface/ICONS/spell_shadow_gathershadows",
383 | ["id"] = 11774
384 | },
385 | },
386 | [52] = {
387 | [1] = {
388 | ["name"] = "Lash of Pain",
389 | ["rank"] = 5,
390 | ["cost"] = 18000,
391 | ["texture"] = "Interface/ICONS/spell_shadow_curse",
392 | ["id"] = 11779
393 | },
394 | [2] = {
395 | ["name"] = "Spell Lock",
396 | ["rank"] = 2,
397 | ["cost"] = 18000,
398 | ["texture"] = "Interface/ICONS/spell_shadow_mindrot",
399 | ["id"] = 19647
400 | },
401 | },
402 | [54] = {
403 | [1] = {
404 | ["name"] = "Devour Magic",
405 | ["rank"] = 4,
406 | ["cost"] = 20000,
407 | ["texture"] = "Interface/ICONS/spell_nature_purge",
408 | ["id"] = 19736
409 | },
410 | [2] = {
411 | ["name"] = "Fire Shield",
412 | ["rank"] = 5,
413 | ["cost"] = 20000,
414 | ["texture"] = "Interface/ICONS/spell_fire_firearmor",
415 | ["id"] = 11771
416 | },
417 | },
418 | [56] = {
419 | [1] = {
420 | ["name"] = "Sacrifice",
421 | ["rank"] = 6,
422 | ["cost"] = 22000,
423 | ["texture"] = "Interface/ICONS/spell_shadow_sacrificialshield",
424 | ["id"] = 19443
425 | },
426 | [2] = {
427 | ["name"] = "Tainted Blood",
428 | ["rank"] = 4,
429 | ["cost"] = 22000,
430 | ["texture"] = "Interface/ICONS/spell_shadow_lifedrain",
431 | ["id"] = 19660
432 | },
433 | },
434 | [58] = {
435 | [1] = {
436 | ["name"] = "Consume Shadows",
437 | ["rank"] = 6,
438 | ["cost"] = 24000,
439 | ["texture"] = "Interface/ICONS/spell_shadow_antishadow",
440 | ["id"] = 17854
441 | },
442 | [2] = {
443 | ["name"] = "Firebolt",
444 | ["rank"] = 7,
445 | ["cost"] = 24000,
446 | ["texture"] = "Interface/ICONS/spell_fire_firebolt",
447 | ["id"] = 11763
448 | },
449 | [3] = {
450 | ["name"] = "Soothing Kiss",
451 | ["rank"] = 4,
452 | ["cost"] = 24000,
453 | ["texture"] = "Interface/ICONS/spell_shadow_soothingkiss",
454 | ["id"] = 11785
455 | },
456 | },
457 | [60] = {
458 | [1] = {
459 | ["name"] = "Lash of Pain",
460 | ["rank"] = 6,
461 | ["cost"] = 26000,
462 | ["texture"] = "Interface/ICONS/spell_shadow_curse",
463 | ["id"] = 11780
464 | },
465 | [2] = {
466 | ["name"] = "Suffering",
467 | ["rank"] = 4,
468 | ["cost"] = 26000,
469 | ["texture"] = "Interface/ICONS/spell_shadow_blackplague",
470 | ["id"] = 17752
471 | },
472 | [3] = {
473 | ["name"] = "Torment",
474 | ["rank"] = 6,
475 | ["cost"] = 26000,
476 | ["texture"] = "Interface/ICONS/spell_shadow_gathershadows",
477 | ["id"] = 11775
478 | },
479 | },
480 | }
481 |
--------------------------------------------------------------------------------
/Database/Warrior.lua:
--------------------------------------------------------------------------------
1 | local _, FieldGuide = ...
2 |
3 | FieldGuide.WARRIOR = {
4 | [2] = {
5 | [1] = {
6 | ["name"] = "Battle Shout",
7 | ["rank"] = 1,
8 | ["cost"] = 10,
9 | ["texture"] = "Interface/ICONS/ability_warrior_battleshout",
10 | ["id"] = 6673
11 | },
12 | },
13 | [4] = {
14 | [1] = {
15 | ["name"] = "Charge",
16 | ["rank"] = 1,
17 | ["cost"] = 100,
18 | ["texture"] = "Interface/ICONS/ability_warrior_charge",
19 | ["id"] = 100
20 | },
21 | [2] = {
22 | ["name"] = "Rend",
23 | ["rank"] = 1,
24 | ["cost"] = 100,
25 | ["texture"] = "Interface/ICONS/ability_gouge",
26 | ["id"] = 772
27 | },
28 | },
29 | [6] = {
30 | [1] = {
31 | ["name"] = "Parry",
32 | ["rank"] = 1,
33 | ["cost"] = 100,
34 | ["texture"] = "Interface/ICONS/ability_parry",
35 | ["id"] = 3127
36 | },
37 | [2] = {
38 | ["name"] = "Thunder Clap",
39 | ["rank"] = 1,
40 | ["cost"] = 100,
41 | ["texture"] = "Interface/ICONS/spell_nature_thunderclap",
42 | ["id"] = 6343
43 | },
44 | },
45 | [8] = {
46 | [1] = {
47 | ["name"] = "Hamstring",
48 | ["rank"] = 1,
49 | ["cost"] = 200,
50 | ["texture"] = "Interface/ICONS/ability_shockwave",
51 | ["id"] = 1715
52 | },
53 | [2] = {
54 | ["name"] = "Heroic Strike",
55 | ["rank"] = 2,
56 | ["cost"] = 200,
57 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
58 | ["id"] = 284
59 | },
60 | },
61 | [10] = {
62 | [1] = {
63 | ["name"] = "Rend",
64 | ["rank"] = 2,
65 | ["cost"] = 600,
66 | ["texture"] = "Interface/ICONS/ability_gouge",
67 | ["id"] = 6546
68 | },
69 | [2] = {
70 | ["name"] = "Bloodrage",
71 | ["rank"] = 1,
72 | ["cost"] = 600,
73 | ["texture"] = "Interface/ICONS/ability_racial_bloodrage",
74 | ["id"] = 2687
75 | },
76 | [3] = {
77 | ["name"] = "Defensive Stance",
78 | ["rank"] = 1,
79 | ["cost"] = 0,
80 | ["texture"] = "Interface/ICONS/ability_warrior_defensivestance",
81 | ["id"] = 71
82 | },
83 | [4] = {
84 | ["name"] = "Sunder Armor",
85 | ["rank"] = 1,
86 | ["cost"] = 0,
87 | ["texture"] = "Interface/ICONS/ability_warrior_sunder",
88 | ["id"] = 7386
89 | },
90 | [5] = {
91 | ["name"] = "Taunt",
92 | ["rank"] = 1,
93 | ["cost"] = 0,
94 | ["texture"] = "Interface/ICONS/spell_nature_reincarnation",
95 | ["id"] = 355
96 | },
97 | },
98 | [12] = {
99 | [1] = {
100 | ["name"] = "Overpower",
101 | ["rank"] = 1,
102 | ["cost"] = 1000,
103 | ["texture"] = "Interface/ICONS/ability_meleedamage",
104 | ["id"] = 7384
105 | },
106 | [2] = {
107 | ["name"] = "Battle Shout",
108 | ["rank"] = 2,
109 | ["cost"] = 1000,
110 | ["texture"] = "Interface/ICONS/ability_warrior_battleshout",
111 | ["id"] = 5242
112 | },
113 | [3] = {
114 | ["name"] = "Shield Bash",
115 | ["rank"] = 1,
116 | ["cost"] = 1000,
117 | ["texture"] = "Interface/ICONS/ability_warrior_shieldbash",
118 | ["id"] = 72
119 | },
120 | },
121 | [14] = {
122 | [1] = {
123 | ["name"] = "Demoralizing Shout",
124 | ["rank"] = 1,
125 | ["cost"] = 1500,
126 | ["texture"] = "Interface/ICONS/ability_warrior_warcry",
127 | ["id"] = 1160
128 | },
129 | [2] = {
130 | ["name"] = "Revenge",
131 | ["rank"] = 1,
132 | ["cost"] = 1500,
133 | ["texture"] = "Interface/ICONS/ability_warrior_revenge",
134 | ["id"] = 6572
135 | },
136 | },
137 | [16] = {
138 | [1] = {
139 | ["name"] = "Heroic Strike",
140 | ["rank"] = 3,
141 | ["cost"] = 2000,
142 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
143 | ["id"] = 285
144 | },
145 | [2] = {
146 | ["name"] = "Mocking Blow",
147 | ["rank"] = 1,
148 | ["cost"] = 2000,
149 | ["texture"] = "Interface/ICONS/ability_warrior_punishingblow",
150 | ["id"] = 694
151 | },
152 | [3] = {
153 | ["name"] = "Shield Block",
154 | ["rank"] = 1,
155 | ["cost"] = 2000,
156 | ["texture"] = "Interface/ICONS/ability_defend",
157 | ["id"] = 2565
158 | },
159 | },
160 | [18] = {
161 | [1] = {
162 | ["name"] = "Thunder Clap",
163 | ["rank"] = 2,
164 | ["cost"] = 3000,
165 | ["texture"] = "Interface/ICONS/spell_nature_thunderclap",
166 | ["id"] = 8198
167 | },
168 | [2] = {
169 | ["name"] = "Disarm",
170 | ["rank"] = 1,
171 | ["cost"] = 3000,
172 | ["texture"] = "Interface/ICONS/ability_warrior_disarm",
173 | ["id"] = 676
174 | },
175 | },
176 | [20] = {
177 | [1] = {
178 | ["name"] = "Dual Wield",
179 | ["rank"] = 1,
180 | ["cost"] = 4000,
181 | ["texture"] = "Interface/ICONS/ability_dualwield",
182 | ["id"] = 674
183 | },
184 | [2] = {
185 | ["name"] = "Rend",
186 | ["rank"] = 3,
187 | ["cost"] = 4000,
188 | ["texture"] = "Interface/ICONS/ability_gouge",
189 | ["id"] = 6547
190 | },
191 | [3] = {
192 | ["name"] = "Retaliation",
193 | ["rank"] = 1,
194 | ["cost"] = 4000,
195 | ["texture"] = "Interface/ICONS/ability_warrior_challange",
196 | ["id"] = 20230
197 | },
198 | [4] = {
199 | ["name"] = "Cleave",
200 | ["rank"] = 1,
201 | ["cost"] = 4000,
202 | ["texture"] = "Interface/ICONS/ability_warrior_cleave",
203 | ["id"] = 845
204 | },
205 | },
206 | [22] = {
207 | [1] = {
208 | ["name"] = "Battle Shout",
209 | ["rank"] = 3,
210 | ["cost"] = 6000,
211 | ["texture"] = "Interface/ICONS/ability_warrior_battleshout",
212 | ["id"] = 6192
213 | },
214 | [2] = {
215 | ["name"] = "Intimidating Shout",
216 | ["rank"] = 1,
217 | ["cost"] = 6000,
218 | ["texture"] = "Interface/ICONS/ability_golemthunderclap",
219 | ["id"] = 5246
220 | },
221 | [3] = {
222 | ["name"] = "Sunder Armor",
223 | ["rank"] = 2,
224 | ["cost"] = 6000,
225 | ["texture"] = "Interface/ICONS/ability_warrior_sunder",
226 | ["id"] = 7405
227 | },
228 | },
229 | [24] = {
230 | [1] = {
231 | ["name"] = "Heroic Strike",
232 | ["rank"] = 4,
233 | ["cost"] = 8000,
234 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
235 | ["id"] = 1608
236 | },
237 | [2] = {
238 | ["name"] = "Demoralizing Shout",
239 | ["rank"] = 2,
240 | ["cost"] = 8000,
241 | ["texture"] = "Interface/ICONS/ability_warrior_warcry",
242 | ["id"] = 6190
243 | },
244 | [3] = {
245 | ["name"] = "Execute",
246 | ["rank"] = 1,
247 | ["cost"] = 8000,
248 | ["texture"] = "Interface/ICONS/inv_sword_48",
249 | ["id"] = 5308
250 | },
251 | [4] = {
252 | ["name"] = "Revenge",
253 | ["rank"] = 2,
254 | ["cost"] = 8000,
255 | ["texture"] = "Interface/ICONS/ability_warrior_revenge",
256 | ["id"] = 6574
257 | },
258 | },
259 | [26] = {
260 | [1] = {
261 | ["name"] = "Charge",
262 | ["rank"] = 2,
263 | ["cost"] = 10000,
264 | ["texture"] = "Interface/ICONS/ability_warrior_charge",
265 | ["id"] = 6178
266 | },
267 | [2] = {
268 | ["name"] = "Mocking Blow",
269 | ["rank"] = 2,
270 | ["cost"] = 10000,
271 | ["texture"] = "Interface/ICONS/ability_warrior_punishingblow",
272 | ["id"] = 7400
273 | },
274 | [3] = {
275 | ["name"] = "Challenging Shout",
276 | ["rank"] = 1,
277 | ["cost"] = 10000,
278 | ["texture"] = "Interface/ICONS/ability_bullrush",
279 | ["id"] = 1161
280 | },
281 | },
282 | [28] = {
283 | [1] = {
284 | ["name"] = "Overpower",
285 | ["rank"] = 2,
286 | ["cost"] = 11000,
287 | ["texture"] = "Interface/ICONS/ability_meleedamage",
288 | ["id"] = 7887
289 | },
290 | [2] = {
291 | ["name"] = "Thunder Clap",
292 | ["rank"] = 3,
293 | ["cost"] = 11000,
294 | ["texture"] = "Interface/ICONS/spell_nature_thunderclap",
295 | ["id"] = 8204
296 | },
297 | [3] = {
298 | ["name"] = "Shield Wall",
299 | ["rank"] = 1,
300 | ["cost"] = 11000,
301 | ["texture"] = "Interface/ICONS/ability_warrior_shieldwall",
302 | ["id"] = 871
303 | },
304 | },
305 | [30] = {
306 | [1] = {
307 | ["name"] = "Rend",
308 | ["rank"] = 4,
309 | ["cost"] = 12000,
310 | ["texture"] = "Interface/ICONS/ability_gouge",
311 | ["id"] = 6548
312 | },
313 | [2] = {
314 | ["name"] = "Berserker Stance",
315 | ["rank"] = 1,
316 | ["cost"] = 0,
317 | ["texture"] = "Interface/ICONS/ability_racial_avatar",
318 | ["id"] = 2458
319 | },
320 | [3] = {
321 | ["name"] = "Cleave",
322 | ["rank"] = 2,
323 | ["cost"] = 12000,
324 | ["texture"] = "Interface/ICONS/ability_warrior_cleave",
325 | ["id"] = 7369
326 | },
327 | [4] = {
328 | ["name"] = "Intercept",
329 | ["rank"] = 1,
330 | ["cost"] = 0,
331 | ["texture"] = "Interface/ICONS/ability_rogue_sprint",
332 | ["id"] = 20252
333 | },
334 | [5] = {
335 | ["name"] = "Slam",
336 | ["rank"] = 1,
337 | ["cost"] = 12000,
338 | ["texture"] = "Interface/ICONS/ability_warrior_decisivestrike",
339 | ["id"] = 1464
340 | },
341 | },
342 | [32] = {
343 | [1] = {
344 | ["name"] = "Hamstring",
345 | ["rank"] = 2,
346 | ["cost"] = 14000,
347 | ["texture"] = "Interface/ICONS/ability_shockwave",
348 | ["id"] = 7372
349 | },
350 | [2] = {
351 | ["name"] = "Heroic Strike",
352 | ["rank"] = 5,
353 | ["cost"] = 14000,
354 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
355 | ["id"] = 11564
356 | },
357 | [3] = {
358 | ["name"] = "Battle Shout",
359 | ["rank"] = 4,
360 | ["cost"] = 14000,
361 | ["texture"] = "Interface/ICONS/ability_warrior_battleshout",
362 | ["id"] = 11549
363 | },
364 | [4] = {
365 | ["name"] = "Berserker Rage",
366 | ["rank"] = 1,
367 | ["cost"] = 14000,
368 | ["texture"] = "Interface/ICONS/spell_nature_ancestralguardian",
369 | ["id"] = 18499
370 | },
371 | [5] = {
372 | ["name"] = "Execute",
373 | ["rank"] = 2,
374 | ["cost"] = 14000,
375 | ["texture"] = "Interface/ICONS/inv_sword_48",
376 | ["id"] = 20658
377 | },
378 | [6] = {
379 | ["name"] = "Shield Bash",
380 | ["rank"] = 2,
381 | ["cost"] = 14000,
382 | ["texture"] = "Interface/ICONS/ability_warrior_shieldbash",
383 | ["id"] = 1671
384 | },
385 | },
386 | [34] = {
387 | [1] = {
388 | ["name"] = "Demoralizing Shout",
389 | ["rank"] = 3,
390 | ["cost"] = 16000,
391 | ["texture"] = "Interface/ICONS/ability_warrior_warcry",
392 | ["id"] = 11554
393 | },
394 | [2] = {
395 | ["name"] = "Revenge",
396 | ["rank"] = 3,
397 | ["cost"] = 16000,
398 | ["texture"] = "Interface/ICONS/ability_warrior_revenge",
399 | ["id"] = 7379
400 | },
401 | [3] = {
402 | ["name"] = "Sunder Armor",
403 | ["rank"] = 3,
404 | ["cost"] = 16000,
405 | ["texture"] = "Interface/ICONS/ability_warrior_sunder",
406 | ["id"] = 8380
407 | },
408 | },
409 | [36] = {
410 | [1] = {
411 | ["name"] = "Mocking Blow",
412 | ["rank"] = 3,
413 | ["cost"] = 18000,
414 | ["texture"] = "Interface/ICONS/ability_warrior_punishingblow",
415 | ["id"] = 7402
416 | },
417 | [2] = {
418 | ["name"] = "Whirlwind",
419 | ["rank"] = 1,
420 | ["cost"] = 18000,
421 | ["texture"] = "Interface/ICONS/ability_whirlwind",
422 | ["id"] = 1680
423 | },
424 | },
425 | [38] = {
426 | [1] = {
427 | ["name"] = "Thunder Clap",
428 | ["rank"] = 4,
429 | ["cost"] = 20000,
430 | ["texture"] = "Interface/ICONS/spell_nature_thunderclap",
431 | ["id"] = 8205
432 | },
433 | [2] = {
434 | ["name"] = "Pummel",
435 | ["rank"] = 1,
436 | ["cost"] = 20000,
437 | ["texture"] = "Interface/ICONS/inv_gauntlets_04",
438 | ["id"] = 6552
439 | },
440 | [3] = {
441 | ["name"] = "Slam",
442 | ["rank"] = 2,
443 | ["cost"] = 20000,
444 | ["texture"] = "Interface/ICONS/ability_warrior_decisivestrike",
445 | ["id"] = 8820
446 | },
447 | },
448 | [40] = {
449 | [1] = {
450 | ["name"] = "Plate Mail",
451 | ["rank"] = 1,
452 | ["cost"] = 22000,
453 | ["texture"] = "Interface/ICONS/inv_chest_plate01",
454 | ["id"] = 750
455 | },
456 | [2] = {
457 | ["name"] = "Heroic Strike",
458 | ["rank"] = 6,
459 | ["cost"] = 22000,
460 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
461 | ["id"] = 11565
462 | },
463 | [3] = {
464 | ["name"] = "Rend",
465 | ["rank"] = 5,
466 | ["cost"] = 22000,
467 | ["texture"] = "Interface/ICONS/ability_gouge",
468 | ["id"] = 11572
469 | },
470 | [4] = {
471 | ["name"] = "Cleave",
472 | ["rank"] = 3,
473 | ["cost"] = 22000,
474 | ["texture"] = "Interface/ICONS/ability_warrior_cleave",
475 | ["id"] = 11608
476 | },
477 | [5] = {
478 | ["name"] = "Execute",
479 | ["rank"] = 3,
480 | ["cost"] = 22000,
481 | ["texture"] = "Interface/ICONS/inv_sword_48",
482 | ["id"] = 20660
483 | },
484 | },
485 | [42] = {
486 | [1] = {
487 | ["name"] = "Battle Shout",
488 | ["rank"] = 5,
489 | ["cost"] = 32000,
490 | ["texture"] = "Interface/ICONS/ability_warrior_battleshout",
491 | ["id"] = 11550
492 | },
493 | [2] = {
494 | ["name"] = "Intercept",
495 | ["rank"] = 2,
496 | ["cost"] = 32000,
497 | ["texture"] = "Interface/ICONS/ability_rogue_sprint",
498 | ["id"] = 20616
499 | },
500 | },
501 | [44] = {
502 | [1] = {
503 | ["name"] = "Overpower",
504 | ["rank"] = 3,
505 | ["cost"] = 34000,
506 | ["texture"] = "Interface/ICONS/ability_meleedamage",
507 | ["id"] = 11584
508 | },
509 | [2] = {
510 | ["name"] = "Demoralizing Shout",
511 | ["rank"] = 4,
512 | ["cost"] = 34000,
513 | ["texture"] = "Interface/ICONS/ability_warrior_warcry",
514 | ["id"] = 11555
515 | },
516 | [3] = {
517 | ["name"] = "Revenge",
518 | ["rank"] = 4,
519 | ["cost"] = 34000,
520 | ["texture"] = "Interface/ICONS/ability_warrior_revenge",
521 | ["id"] = 11600
522 | },
523 | },
524 | [46] = {
525 | [1] = {
526 | ["name"] = "Charge",
527 | ["rank"] = 3,
528 | ["cost"] = 36000,
529 | ["texture"] = "Interface/ICONS/ability_warrior_charge",
530 | ["id"] = 11578
531 | },
532 | [2] = {
533 | ["name"] = "Mocking Blow",
534 | ["rank"] = 4,
535 | ["cost"] = 36000,
536 | ["texture"] = "Interface/ICONS/ability_warrior_punishingblow",
537 | ["id"] = 20559
538 | },
539 | [3] = {
540 | ["name"] = "Slam",
541 | ["rank"] = 3,
542 | ["cost"] = 36000,
543 | ["texture"] = "Interface/ICONS/ability_warrior_decisivestrike",
544 | ["id"] = 11604
545 | },
546 | [4] = {
547 | ["name"] = "Sunder Armor",
548 | ["rank"] = 4,
549 | ["cost"] = 36000,
550 | ["texture"] = "Interface/ICONS/ability_warrior_sunder",
551 | ["id"] = 11596
552 | },
553 | },
554 | [48] = {
555 | [1] = {
556 | ["name"] = "Heroic Strike",
557 | ["rank"] = 7,
558 | ["cost"] = 40000,
559 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
560 | ["id"] = 11566
561 | },
562 | [2] = {
563 | ["name"] = "Mortal Strike",
564 | ["rank"] = 2,
565 | ["cost"] = 200, -- Typo on pservers?
566 | ["texture"] = "Interface/ICONS/ability_warrior_savageblow",
567 | ["id"] = 21551,
568 | ["talent"] = true
569 | },
570 | [3] = {
571 | ["name"] = "Thunder Clap",
572 | ["rank"] = 5,
573 | ["cost"] = 40000,
574 | ["texture"] = "Interface/ICONS/spell_nature_thunderclap",
575 | ["id"] = 11580
576 | },
577 | [4] = {
578 | ["name"] = "Bloodthirst",
579 | ["rank"] = 2,
580 | ["cost"] = 2000,
581 | ["texture"] = "Interface/ICONS/spell_nature_bloodlust",
582 | ["id"] = 23892,
583 | ["talent"] = true
584 | },
585 | [5] = {
586 | ["name"] = "Execute",
587 | ["rank"] = 4,
588 | ["cost"] = 40000,
589 | ["texture"] = "Interface/ICONS/inv_sword_48",
590 | ["id"] = 20661
591 | },
592 | [6] = {
593 | ["name"] = "Shield Slam",
594 | ["rank"] = 2,
595 | ["cost"] = 200, -- Typo on pservers?
596 | ["texture"] = "Interface/ICONS/inv_shield_05",
597 | ["id"] = 23923,
598 | ["talent"] = true
599 | },
600 | },
601 | [50] = {
602 | [1] = {
603 | ["name"] = "Rend",
604 | ["rank"] = 6,
605 | ["cost"] = 42000,
606 | ["texture"] = "Interface/ICONS/ability_gouge",
607 | ["id"] = 11573
608 | },
609 | [2] = {
610 | ["name"] = "Cleave",
611 | ["rank"] = 4,
612 | ["cost"] = 42000,
613 | ["texture"] = "Interface/ICONS/ability_warrior_cleave",
614 | ["id"] = 11609
615 | },
616 | [3] = {
617 | ["name"] = "Recklessness",
618 | ["rank"] = 1,
619 | ["cost"] = 42000,
620 | ["texture"] = "Interface/ICONS/ability_criticalstrike",
621 | ["id"] = 1719
622 | },
623 | },
624 | [52] = {
625 | [1] = {
626 | ["name"] = "Battle Shout",
627 | ["rank"] = 6,
628 | ["cost"] = 54000,
629 | ["texture"] = "Interface/ICONS/ability_warrior_battleshout",
630 | ["id"] = 11551
631 | },
632 | [2] = {
633 | ["name"] = "Intercept",
634 | ["rank"] = 3,
635 | ["cost"] = 54000,
636 | ["texture"] = "Interface/ICONS/ability_rogue_sprint",
637 | ["id"] = 20617
638 | },
639 | [3] = {
640 | ["name"] = "Shield Bash",
641 | ["rank"] = 3,
642 | ["cost"] = 54000,
643 | ["texture"] = "Interface/ICONS/ability_warrior_shieldbash",
644 | ["id"] = 1672
645 | },
646 | },
647 | [54] = {
648 | [1] = {
649 | ["name"] = "Hamstring",
650 | ["rank"] = 3,
651 | ["cost"] = 56000,
652 | ["texture"] = "Interface/ICONS/ability_shockwave",
653 | ["id"] = 7373
654 | },
655 | [2] = {
656 | ["name"] = "Mortal Strike",
657 | ["rank"] = 3,
658 | ["cost"] = 2800,
659 | ["texture"] = "Interface/ICONS/ability_warrior_savageblow",
660 | ["id"] = 21552,
661 | ["talent"] = true
662 | },
663 | [3] = {
664 | ["name"] = "Bloodthirst",
665 | ["rank"] = 3,
666 | ["cost"] = 2800,
667 | ["texture"] = "Interface/ICONS/spell_nature_bloodlust",
668 | ["id"] = 23893,
669 | ["talent"] = true
670 | },
671 | [4] = {
672 | ["name"] = "Demoralizing Shout",
673 | ["rank"] = 5,
674 | ["cost"] = 56000,
675 | ["texture"] = "Interface/ICONS/ability_warrior_warcry",
676 | ["id"] = 11556
677 | },
678 | [5] = {
679 | ["name"] = "Slam",
680 | ["rank"] = 4,
681 | ["cost"] = 56000,
682 | ["texture"] = "Interface/ICONS/ability_warrior_decisivestrike",
683 | ["id"] = 11605
684 | },
685 | [6] = {
686 | ["name"] = "Revenge",
687 | ["rank"] = 5,
688 | ["cost"] = 56000,
689 | ["texture"] = "Interface/ICONS/ability_warrior_revenge",
690 | ["id"] = 11601
691 | },
692 | [7] = {
693 | ["name"] = "Shield Slam",
694 | ["rank"] = 3,
695 | ["cost"] = 2800,
696 | ["texture"] = "Interface/ICONS/inv_shield_05",
697 | ["id"] = 23924,
698 | ["talent"] = true
699 | },
700 | },
701 | [56] = {
702 | [1] = {
703 | ["name"] = "Heroic Strike",
704 | ["rank"] = 8,
705 | ["cost"] = 58000,
706 | ["texture"] = "Interface/ICONS/ability_rogue_ambush",
707 | ["id"] = 11567
708 | },
709 | [2] = {
710 | ["name"] = "Mocking Blow",
711 | ["rank"] = 5,
712 | ["cost"] = 58000,
713 | ["texture"] = "Interface/ICONS/ability_warrior_punishingblow",
714 | ["id"] = 20560
715 | },
716 | [3] = {
717 | ["name"] = "Execute",
718 | ["rank"] = 5,
719 | ["cost"] = 58000,
720 | ["texture"] = "Interface/ICONS/inv_sword_48",
721 | ["id"] = 20662
722 | },
723 | },
724 | [58] = {
725 | [1] = {
726 | ["name"] = "Thunder Clap",
727 | ["rank"] = 6,
728 | ["cost"] = 60000,
729 | ["texture"] = "Interface/ICONS/spell_nature_thunderclap",
730 | ["id"] = 11581
731 | },
732 | [2] = {
733 | ["name"] = "Pummel",
734 | ["rank"] = 2,
735 | ["cost"] = 60000,
736 | ["texture"] = "Interface/ICONS/inv_gauntlets_04",
737 | ["id"] = 6554
738 | },
739 | [3] = {
740 | ["name"] = "Sunder Armor",
741 | ["rank"] = 5,
742 | ["cost"] = 60000,
743 | ["texture"] = "Interface/ICONS/ability_warrior_sunder",
744 | ["id"] = 11597
745 | },
746 | },
747 | [60] = {
748 | [1] = {
749 | ["name"] = "Mortal Strike",
750 | ["rank"] = 4,
751 | ["cost"] = 3100,
752 | ["texture"] = "Interface/ICONS/ability_warrior_savageblow",
753 | ["id"] = 21553,
754 | ["talent"] = true
755 | },
756 | [2] = {
757 | ["name"] = "Overpower",
758 | ["rank"] = 4,
759 | ["cost"] = 62000,
760 | ["texture"] = "Interface/ICONS/ability_meleedamage",
761 | ["id"] = 11585
762 | },
763 | [3] = {
764 | ["name"] = "Rend",
765 | ["rank"] = 7,
766 | ["cost"] = 62000,
767 | ["texture"] = "Interface/ICONS/ability_gouge",
768 | ["id"] = 11574
769 | },
770 | [4] = {
771 | ["name"] = "Bloodthirst",
772 | ["rank"] = 4,
773 | ["cost"] = 3100,
774 | ["texture"] = "Interface/ICONS/spell_nature_bloodlust",
775 | ["id"] = 23894,
776 | ["talent"] = true
777 | },
778 | [5] = {
779 | ["name"] = "Cleave",
780 | ["rank"] = 5,
781 | ["cost"] = 62000,
782 | ["texture"] = "Interface/ICONS/ability_warrior_cleave",
783 | ["id"] = 20569
784 | },
785 | [6] = {
786 | ["name"] = "Shield Slam",
787 | ["rank"] = 4,
788 | ["cost"] = 3100,
789 | ["texture"] = "Interface/ICONS/inv_shield_05",
790 | ["id"] = 23925,
791 | ["talent"] = true
792 | },
793 | },
794 | }
795 |
--------------------------------------------------------------------------------
/Database/WeaponSkills.lua:
--------------------------------------------------------------------------------
1 | local _, FieldGuide = ...
2 |
3 | local weapons = {
4 | ["bows"] = {
5 | ["name"] = "Bows",
6 | ["rank"] = 1,
7 | ["cost"] = 1000,
8 | ["texture"] = "Interface/ICONS/inv_weapon_bow_05",
9 | ["id"] = 264
10 | },
11 | ["crossbows"] = {
12 | ["name"] = "Crossbows",
13 | ["rank"] = 1,
14 | ["cost"] = 1000,
15 | ["texture"] = "Interface/ICONS/inv_weapon_crossbow_01",
16 | ["id"] = 5011
17 | },
18 | ["daggers"] = {
19 | ["name"] = "Daggers",
20 | ["rank"] = 1,
21 | ["cost"] = 1000,
22 | ["texture"] = "Interface/ICONS/ability_steelmelee",
23 | ["id"] = 1180
24 | },
25 | ["fist_weapons"] = {
26 | ["name"] = "Fist Weapons",
27 | ["rank"] = 1,
28 | ["cost"] = 1000,
29 | ["texture"] = "Interface/ICONS/inv_gauntlets_04",
30 | ["id"] = 15590
31 | },
32 | ["guns"] = {
33 | ["name"] = "Guns",
34 | ["rank"] = 1,
35 | ["cost"] = 1000,
36 | ["texture"] = "Interface/ICONS/inv_weapon_rifle_01",
37 | ["id"] = 266
38 | },
39 | ["one_handed_axes"] = {
40 | ["name"] = "Axes",
41 | ["rank"] = 1,
42 | ["cost"] = 1000,
43 | ["texture"] = "Interface/ICONS/inv_axe_01",
44 | ["id"] = 196
45 | },
46 | ["one_handed_maces"] = {
47 | ["name"] = "Maces",
48 | ["rank"] = 1,
49 | ["cost"] = 1000,
50 | ["texture"] = "Interface/ICONS/inv_mace_01",
51 | ["id"] = 198
52 | },
53 | ["one_handed_swords"] = {
54 | ["name"] = "Swords",
55 | ["rank"] = 1,
56 | ["cost"] = 1000,
57 | ["texture"] = "Interface/ICONS/ability_meleedamage",
58 | ["id"] = 201
59 | },
60 | ["polearms"] = {
61 | ["name"] = "Polearms",
62 | ["rank"] = 1,
63 | ["cost"] = 10000,
64 | ["texture"] = "Interface/ICONS/inv_spear_06",
65 | ["id"] = 200
66 | },
67 | ["staves"] = {
68 | ["name"] = "Staves",
69 | ["rank"] = 1,
70 | ["cost"] = 1000,
71 | ["texture"] = "Interface/ICONS/inv_staff_08",
72 | ["id"] = 227
73 | },
74 | ["thrown"] = {
75 | ["name"] = "Thrown",
76 | ["rank"] = 1,
77 | ["cost"] = 1000,
78 | ["texture"] = "Interface/ICONS/inv_throwingknife_02",
79 | ["id"] = 2567
80 | },
81 | ["two_handed_axes"] = {
82 | ["name"] = "Two-Handed Axes",
83 | ["rank"] = 1,
84 | ["cost"] = 1000,
85 | ["texture"] = "Interface/ICONS/inv_axe_04",
86 | ["id"] = 197
87 | },
88 | ["two_handed_maces"] = {
89 | ["name"] = "Two-Handed Maces",
90 | ["rank"] = 1,
91 | ["cost"] = 1000,
92 | ["texture"] = "Interface/ICONS/inv_mace_04",
93 | ["id"] = 199
94 | },
95 | ["two_handed_swords"] = {
96 | ["name"] = "Two-Handed Swords",
97 | ["rank"] = 1,
98 | ["cost"] = 1000,
99 | ["texture"] = "Interface/ICONS/ability_meleedamage",
100 | ["id"] = 202
101 | },
102 | ["wands"] = {
103 | ["name"] = "Wands",
104 | ["rank"] = 1,
105 | ["cost"] = 1000,
106 | ["texture"] = "Interface/ICONS/ability_shootwand",
107 | ["id"] = 5009
108 | }
109 | }
110 |
111 | FieldGuide.WEAPONS = {
112 | [1] = { -- Warrior.
113 | FieldGuide.copy(weapons.bows),
114 | FieldGuide.copy(weapons.crossbows),
115 | FieldGuide.copy(weapons.daggers),
116 | FieldGuide.copy(weapons.fist_weapons),
117 | FieldGuide.copy(weapons.guns),
118 | FieldGuide.copy(weapons.one_handed_axes),
119 | FieldGuide.copy(weapons.one_handed_maces),
120 | FieldGuide.copy(weapons.one_handed_swords),
121 | FieldGuide.copy(weapons.polearms),
122 | FieldGuide.copy(weapons.staves),
123 | FieldGuide.copy(weapons.thrown),
124 | FieldGuide.copy(weapons.two_handed_axes),
125 | FieldGuide.copy(weapons.two_handed_maces),
126 | FieldGuide.copy(weapons.two_handed_swords)
127 | },
128 | [2] = { -- Paladin.
129 | FieldGuide.copy(weapons.one_handed_axes),
130 | FieldGuide.copy(weapons.one_handed_maces),
131 | FieldGuide.copy(weapons.one_handed_swords),
132 | FieldGuide.copy(weapons.polearms),
133 | FieldGuide.copy(weapons.two_handed_axes),
134 | FieldGuide.copy(weapons.two_handed_maces),
135 | FieldGuide.copy(weapons.two_handed_swords)
136 | },
137 | [3] = { -- Hunter.
138 | FieldGuide.copy(weapons.bows),
139 | FieldGuide.copy(weapons.crossbows),
140 | FieldGuide.copy(weapons.daggers),
141 | FieldGuide.copy(weapons.fist_weapons),
142 | FieldGuide.copy(weapons.guns),
143 | FieldGuide.copy(weapons.one_handed_axes),
144 | FieldGuide.copy(weapons.one_handed_swords),
145 | FieldGuide.copy(weapons.polearms),
146 | FieldGuide.copy(weapons.staves),
147 | FieldGuide.copy(weapons.thrown),
148 | FieldGuide.copy(weapons.two_handed_axes),
149 | FieldGuide.copy(weapons.two_handed_swords)
150 | },
151 | [4] = { -- Rogue.
152 | FieldGuide.copy(weapons.bows),
153 | FieldGuide.copy(weapons.crossbows),
154 | FieldGuide.copy(weapons.daggers),
155 | FieldGuide.copy(weapons.fist_weapons),
156 | FieldGuide.copy(weapons.guns),
157 | FieldGuide.copy(weapons.one_handed_maces),
158 | FieldGuide.copy(weapons.one_handed_swords),
159 | FieldGuide.copy(weapons.thrown)
160 | },
161 | [5] = { -- Priest.
162 | FieldGuide.copy(weapons.daggers),
163 | FieldGuide.copy(weapons.one_handed_maces),
164 | FieldGuide.copy(weapons.staves),
165 | FieldGuide.copy(weapons.wands)
166 | },
167 | [6] = { -- Shaman.
168 | FieldGuide.copy(weapons.daggers),
169 | FieldGuide.copy(weapons.one_handed_axes),
170 | FieldGuide.copy(weapons.one_handed_maces),
171 | FieldGuide.copy(weapons.staves),
172 | FieldGuide.copy(weapons.two_handed_axes),
173 | FieldGuide.copy(weapons.two_handed_maces)
174 | },
175 | [7] = { -- Mage.
176 | FieldGuide.copy(weapons.daggers),
177 | FieldGuide.copy(weapons.one_handed_swords),
178 | FieldGuide.copy(weapons.staves),
179 | FieldGuide.copy(weapons.wands)
180 | },
181 | [8] = { -- Warlock.
182 | FieldGuide.copy(weapons.daggers),
183 | FieldGuide.copy(weapons.one_handed_swords),
184 | FieldGuide.copy(weapons.staves),
185 | FieldGuide.copy(weapons.wands)
186 | },
187 | [9] = { -- Druid.
188 | FieldGuide.copy(weapons.daggers),
189 | FieldGuide.copy(weapons.fist_weapons),
190 | FieldGuide.copy(weapons.one_handed_maces),
191 | FieldGuide.copy(weapons.staves),
192 | FieldGuide.copy(weapons.two_handed_maces)
193 | },
194 | }
195 |
--------------------------------------------------------------------------------
/FieldGuide.toc:
--------------------------------------------------------------------------------
1 | ## Interface: 11505
2 | ## Title: Field Guide
3 | ## Notes: Shows when spells are trainable and how much each spell costs to train, and other stuff.
4 | ## Author: cloudbells
5 | ## Version: @project-version@
6 | ## SavedVariablesPerCharacter: FieldGuideOptions
7 | ## OptionalDeps: TomTom
8 | ## X-Curse-Project-ID: 333490
9 | ## X-WoWI-ID: 25176
10 |
11 | # Load libraries.
12 | Libraries\LibStub\LibStub.lua
13 | Libraries\CallbackHandler-1.0\CallbackHandler-1.0.lua
14 | Libraries\LibDataBroker-1.1\LibDataBroker-1.1.lua
15 | Libraries\LibDBIcon-1.0\LibDBIcon-1.0.lua
16 | Libraries\HereBeDragons-2.0\HereBeDragons-2.0.lua
17 | Libraries\HereBeDragons-2.0\HereBeDragons-Pins-2.0.lua
18 | Libraries\LibUIDropDownMenu\LibUIDropDownMenu.xml
19 |
20 | # Load utilites.
21 | Util.lua
22 |
23 | # Load spell tables.
24 | Database\WeaponSkills.lua
25 | Database\Druid.lua
26 | Database\Hunter.lua
27 | Database\HunterPets.lua
28 | Database\Mage.lua
29 | Database\Paladin.lua
30 | Database\Priest.lua
31 | Database\Rogue.lua
32 | Database\Shaman.lua
33 | Database\Warlock.lua
34 | Database\WarlockPets.lua
35 | Database\Warrior.lua
36 | Database\Trainers.lua
37 |
38 | # Load core files.
39 | FieldGuide.lua
40 | FieldGuide.xml
41 |
--------------------------------------------------------------------------------
/FieldGuide.xml:
--------------------------------------------------------------------------------
1 |
2 |
37 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | FieldGuide_OnVerticalValueChanged(self, value)
122 |
123 |
124 |
125 |
126 |
127 |
128 |
143 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 | FieldGuide_OnHorizontalValueChanged(self, value)
180 |
181 |
182 |
183 |
184 |
185 |
186 |
201 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 | FieldGuide_ToggleButtons(1)
233 |
234 |
235 |
236 |
237 |
238 |
239 | FieldGuide_ToggleButtons(2)
240 |
241 |
242 |
243 |
244 |
245 |
246 | FieldGuide_ToggleButtons(3)
247 |
248 |
249 |
250 |
255 |
256 |
257 |
258 | FieldGuide_OnLoad(self)
259 | FieldGuideFrame:SetBackdrop({
260 | edgeFile = "Interface/DialogFrame/UI-DialogBox-Border",
261 | edgeSize = 32,
262 | })
263 |
264 |
265 | PlaySound(SOUNDKIT.IG_SPELLBOOK_OPEN)
266 |
267 |
268 | PlaySound(SOUNDKIT.IG_SPELLBOOK_CLOSE)
269 |
270 |
271 | self:StartMoving()
272 |
273 |
274 | self:StopMovingOrSizing()
275 |
276 |
277 | FieldGuide_Scroll(delta)
278 |
279 |
280 | FieldGuide_OnEvent(self, event, ...)
281 |
282 |
283 |
284 |
285 |
--------------------------------------------------------------------------------
/Libraries/CallbackHandler-1.0/CallbackHandler-1.0.lua:
--------------------------------------------------------------------------------
1 | --[[ $Id: CallbackHandler-1.0.lua 22 2018-07-21 14:17:22Z nevcairiel $ ]]
2 | local MAJOR, MINOR = "CallbackHandler-1.0", 7
3 | local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
4 |
5 | if not CallbackHandler then return end -- No upgrade needed
6 |
7 | local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
8 |
9 | -- Lua APIs
10 | local tconcat = table.concat
11 | local assert, error, loadstring = assert, error, loadstring
12 | local setmetatable, rawset, rawget = setmetatable, rawset, rawget
13 | local next, select, pairs, type, tostring = next, select, pairs, type, tostring
14 |
15 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
16 | -- List them here for Mikk's FindGlobals script
17 | -- GLOBALS: geterrorhandler
18 |
19 | local xpcall = xpcall
20 |
21 | local function errorhandler(err)
22 | return geterrorhandler()(err)
23 | end
24 |
25 | local function Dispatch(handlers, ...)
26 | local index, method = next(handlers)
27 | if not method then return end
28 | repeat
29 | xpcall(method, errorhandler, ...)
30 | index, method = next(handlers, index)
31 | until not method
32 | end
33 |
34 | --------------------------------------------------------------------------
35 | -- CallbackHandler:New
36 | --
37 | -- target - target object to embed public APIs in
38 | -- RegisterName - name of the callback registration API, default "RegisterCallback"
39 | -- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
40 | -- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
41 |
42 | function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName)
43 |
44 | RegisterName = RegisterName or "RegisterCallback"
45 | UnregisterName = UnregisterName or "UnregisterCallback"
46 | if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
47 | UnregisterAllName = "UnregisterAllCallbacks"
48 | end
49 |
50 | -- we declare all objects and exported APIs inside this closure to quickly gain access
51 | -- to e.g. function names, the "target" parameter, etc
52 |
53 |
54 | -- Create the registry object
55 | local events = setmetatable({}, meta)
56 | local registry = { recurse=0, events=events }
57 |
58 | -- registry:Fire() - fires the given event/message into the registry
59 | function registry:Fire(eventname, ...)
60 | if not rawget(events, eventname) or not next(events[eventname]) then return end
61 | local oldrecurse = registry.recurse
62 | registry.recurse = oldrecurse + 1
63 |
64 | Dispatch(events[eventname], eventname, ...)
65 |
66 | registry.recurse = oldrecurse
67 |
68 | if registry.insertQueue and oldrecurse==0 then
69 | -- Something in one of our callbacks wanted to register more callbacks; they got queued
70 | for eventname,callbacks in pairs(registry.insertQueue) do
71 | local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
72 | for self,func in pairs(callbacks) do
73 | events[eventname][self] = func
74 | -- fire OnUsed callback?
75 | if first and registry.OnUsed then
76 | registry.OnUsed(registry, target, eventname)
77 | first = nil
78 | end
79 | end
80 | end
81 | registry.insertQueue = nil
82 | end
83 | end
84 |
85 | -- Registration of a callback, handles:
86 | -- self["method"], leads to self["method"](self, ...)
87 | -- self with function ref, leads to functionref(...)
88 | -- "addonId" (instead of self) with function ref, leads to functionref(...)
89 | -- all with an optional arg, which, if present, gets passed as first argument (after self if present)
90 | target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
91 | if type(eventname) ~= "string" then
92 | error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
93 | end
94 |
95 | method = method or eventname
96 |
97 | local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
98 |
99 | if type(method) ~= "string" and type(method) ~= "function" then
100 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
101 | end
102 |
103 | local regfunc
104 |
105 | if type(method) == "string" then
106 | -- self["method"] calling style
107 | if type(self) ~= "table" then
108 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
109 | elseif self==target then
110 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
111 | elseif type(self[method]) ~= "function" then
112 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
113 | end
114 |
115 | if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
116 | local arg=select(1,...)
117 | regfunc = function(...) self[method](self,arg,...) end
118 | else
119 | regfunc = function(...) self[method](self,...) end
120 | end
121 | else
122 | -- function ref with self=object or self="addonId" or self=thread
123 | if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
124 | error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
125 | end
126 |
127 | if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
128 | local arg=select(1,...)
129 | regfunc = function(...) method(arg,...) end
130 | else
131 | regfunc = method
132 | end
133 | end
134 |
135 |
136 | if events[eventname][self] or registry.recurse<1 then
137 | -- if registry.recurse<1 then
138 | -- we're overwriting an existing entry, or not currently recursing. just set it.
139 | events[eventname][self] = regfunc
140 | -- fire OnUsed callback?
141 | if registry.OnUsed and first then
142 | registry.OnUsed(registry, target, eventname)
143 | end
144 | else
145 | -- we're currently processing a callback in this registry, so delay the registration of this new entry!
146 | -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
147 | registry.insertQueue = registry.insertQueue or setmetatable({},meta)
148 | registry.insertQueue[eventname][self] = regfunc
149 | end
150 | end
151 |
152 | -- Unregister a callback
153 | target[UnregisterName] = function(self, eventname)
154 | if not self or self==target then
155 | error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
156 | end
157 | if type(eventname) ~= "string" then
158 | error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
159 | end
160 | if rawget(events, eventname) and events[eventname][self] then
161 | events[eventname][self] = nil
162 | -- Fire OnUnused callback?
163 | if registry.OnUnused and not next(events[eventname]) then
164 | registry.OnUnused(registry, target, eventname)
165 | end
166 | end
167 | if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
168 | registry.insertQueue[eventname][self] = nil
169 | end
170 | end
171 |
172 | -- OPTIONAL: Unregister all callbacks for given selfs/addonIds
173 | if UnregisterAllName then
174 | target[UnregisterAllName] = function(...)
175 | if select("#",...)<1 then
176 | error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
177 | end
178 | if select("#",...)==1 and ...==target then
179 | error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
180 | end
181 |
182 |
183 | for i=1,select("#",...) do
184 | local self = select(i,...)
185 | if registry.insertQueue then
186 | for eventname, callbacks in pairs(registry.insertQueue) do
187 | if callbacks[self] then
188 | callbacks[self] = nil
189 | end
190 | end
191 | end
192 | for eventname, callbacks in pairs(events) do
193 | if callbacks[self] then
194 | callbacks[self] = nil
195 | -- Fire OnUnused callback?
196 | if registry.OnUnused and not next(callbacks) then
197 | registry.OnUnused(registry, target, eventname)
198 | end
199 | end
200 | end
201 | end
202 | end
203 | end
204 |
205 | return registry
206 | end
207 |
208 |
209 | -- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
210 | -- try to upgrade old implicit embeds since the system is selfcontained and
211 | -- relies on closures to work.
212 |
213 |
--------------------------------------------------------------------------------
/Libraries/HereBeDragons-2.0/HereBeDragons-2.0.lua:
--------------------------------------------------------------------------------
1 | -- HereBeDragons is a data API for the World of Warcraft mapping system
2 |
3 | local MAJOR, MINOR = "HereBeDragons-2.0", 16
4 | assert(LibStub, MAJOR .. " requires LibStub")
5 |
6 | local HereBeDragons, oldversion = LibStub:NewLibrary(MAJOR, MINOR)
7 | if not HereBeDragons then return end
8 |
9 | local CBH = LibStub("CallbackHandler-1.0")
10 |
11 | HereBeDragons.eventFrame = HereBeDragons.eventFrame or CreateFrame("Frame")
12 |
13 | HereBeDragons.mapData = HereBeDragons.mapData or {}
14 | HereBeDragons.worldMapData = HereBeDragons.worldMapData or {}
15 | HereBeDragons.transforms = HereBeDragons.transforms or {}
16 | HereBeDragons.callbacks = HereBeDragons.callbacks or CBH:New(HereBeDragons, nil, nil, false)
17 |
18 | local WoWClassic = (WOW_PROJECT_ID == WOW_PROJECT_CLASSIC)
19 | local WoWBC = (WOW_PROJECT_ID == WOW_PROJECT_BURNING_CRUSADE_CLASSIC)
20 |
21 | -- Data Constants
22 | local COSMIC_MAP_ID = 946
23 | local WORLD_MAP_ID = 947
24 |
25 | -- Lua upvalues
26 | local PI2 = math.pi * 2
27 | local atan2 = math.atan2
28 | local pairs, ipairs = pairs, ipairs
29 |
30 | -- WoW API upvalues
31 | local UnitPosition = UnitPosition
32 | local C_Map = C_Map
33 |
34 | -- data table upvalues
35 | local mapData = HereBeDragons.mapData -- table { width, height, left, top, .instance, .name, .mapType }
36 | local worldMapData = HereBeDragons.worldMapData -- table { width, height, left, top }
37 | local transforms = HereBeDragons.transforms
38 |
39 | local currentPlayerUIMapID, currentPlayerUIMapType
40 |
41 | -- Override instance ids for phased content
42 | local instanceIDOverrides = {
43 | -- Draenor
44 | [1152] = 1116, -- Horde Garrison 1
45 | [1330] = 1116, -- Horde Garrison 2
46 | [1153] = 1116, -- Horde Garrison 3
47 | [1154] = 1116, -- Horde Garrison 4 (unused)
48 | [1158] = 1116, -- Alliance Garrison 1
49 | [1331] = 1116, -- Alliance Garrison 2
50 | [1159] = 1116, -- Alliance Garrison 3
51 | [1160] = 1116, -- Alliance Garrison 4 (unused)
52 | [1191] = 1116, -- Ashran PvP Zone
53 | [1203] = 1116, -- Frostfire Finale Scenario
54 | [1207] = 1116, -- Talador Finale Scenario
55 | [1277] = 1116, -- Defense of Karabor Scenario (SMV)
56 | [1402] = 1116, -- Gorgrond Finale Scenario
57 | [1464] = 1116, -- Tanaan
58 | [1465] = 1116, -- Tanaan
59 | -- Legion
60 | [1478] = 1220, -- Temple of Elune Scenario (Val'Sharah)
61 | [1495] = 1220, -- Protection Paladin Artifact Scenario (Stormheim)
62 | [1498] = 1220, -- Havoc Demon Hunter Artifact Scenario (Suramar)
63 | [1502] = 1220, -- Dalaran Underbelly
64 | [1533] = 0, -- Karazhan Artifact Scenario
65 | [1539] = 0, -- Arm Warrior Artifact Tirisfal Scenario
66 | [1612] = 1220, -- Feral Druid Artifact Scenario (Suramar)
67 | [1626] = 1220, -- Suramar Withered Scenario
68 | [1662] = 1220, -- Suramar Invasion Scenario
69 | -- BfA
70 | [2213] = 0, -- Horrific Vision of Stormwind
71 | [2241] = 1, -- Uldum N'zoth assault
72 | [2274] = 1, -- Uldum N'zoth Minor Vision
73 | [2275] = 870, -- Vale of Eternal Blossoms N'zoth Minor Vision
74 | }
75 |
76 | local dynamicInstanceIDOverrides = {}
77 | instanceIDOverrides = setmetatable(instanceIDOverrides, { __index = dynamicInstanceIDOverrides })
78 |
79 | local function overrideInstance(instance) return instanceIDOverrides[instance] or instance end
80 |
81 | -- debug only
82 | HereBeDragons.___DIIDO = dynamicInstanceIDOverrides
83 |
84 | -- gather map info, but only if this isn't an upgrade (or the upgrade version forces a re-map)
85 | if not oldversion or oldversion < 16 then
86 | -- wipe old data, if required, otherwise the upgrade path isn't triggered
87 | if oldversion then
88 | wipe(mapData)
89 | wipe(worldMapData)
90 | wipe(transforms)
91 | end
92 |
93 | -- map transform data extracted from UIMapAssignment.db2 (see HereBeDragons-Scripts on GitHub)
94 | -- format: instanceID, newInstanceID, minY, maxY, minX, maxX, offsetY, offsetX
95 | local transformData
96 | if WoWBC then
97 | transformData = {
98 | { 530, 0, 4800, 16000, -10133.3, -2666.67, -2400, 2662.8 },
99 | { 530, 1, -6933.33, 533.33, -16000, -8000, 10339.7, 17600 },
100 | }
101 | else
102 | transformData = {
103 | { 530, 1, -6933.33, 533.33, -16000, -8000, 9916, 17600 },
104 | { 530, 0, 4800, 16000, -10133.3, -2666.67, -2400, 2400 },
105 | { 732, 0, -3200, 533.3, -533.3, 2666.7, -611.8, 3904.3 },
106 | { 1064, 870, 5391, 8148, 3518, 7655, -2134.2, -2286.6 },
107 | { 1208, 1116, -2666, -2133, -2133, -1600, 10210.7, 2411.4 },
108 | { 1460, 1220, -1066.7, 2133.3, 0, 3200, -2333.9, 966.7 },
109 | { 1599, 1, 4800, 5866.7, -4266.7, -3200, -490.6, -0.4 },
110 | { 1609, 571, 6400, 8533.3, -1600, 533.3, 512.8, 545.3 },
111 | }
112 | end
113 |
114 | local function processTransforms()
115 | for _, transform in pairs(transformData) do
116 | local instanceID, newInstanceID, minY, maxY, minX, maxX, offsetY, offsetX = unpack(transform)
117 | if not transforms[instanceID] then
118 | transforms[instanceID] = {}
119 | end
120 | table.insert(transforms[instanceID], { newInstanceID = newInstanceID, minY = minY, maxY = maxY, minX = minX, maxX = maxX, offsetY = offsetY, offsetX = offsetX })
121 | end
122 | end
123 |
124 | local function applyMapTransforms(instanceID, left, right, top, bottom)
125 | if transforms[instanceID] then
126 | for _, data in ipairs(transforms[instanceID]) do
127 | if left <= data.maxX and right >= data.minX and top <= data.maxY and bottom >= data.minY then
128 | instanceID = data.newInstanceID
129 | left = left + data.offsetX
130 | right = right + data.offsetX
131 | top = top + data.offsetY
132 | bottom = bottom + data.offsetY
133 | break
134 | end
135 | end
136 | end
137 | return instanceID, left, right, top, bottom
138 | end
139 |
140 | local vector00, vector05 = CreateVector2D(0, 0), CreateVector2D(0.5, 0.5)
141 | -- gather the data of one map (by uiMapID)
142 | local function processMap(id, data, parent)
143 | if not id or not data or mapData[id] then return end
144 |
145 | if data.parentMapID and data.parentMapID ~= 0 then
146 | parent = data.parentMapID
147 | elseif not parent then
148 | parent = 0
149 | end
150 |
151 | -- get two positions from the map, we use 0/0 and 0.5/0.5 to avoid issues on some maps where 1/1 is translated inaccurately
152 | local instance, topLeft = C_Map.GetWorldPosFromMapPos(id, vector00)
153 | local _, bottomRight = C_Map.GetWorldPosFromMapPos(id, vector05)
154 | if topLeft and bottomRight then
155 | local top, left = topLeft:GetXY()
156 | local bottom, right = bottomRight:GetXY()
157 | bottom = top + (bottom - top) * 2
158 | right = left + (right - left) * 2
159 |
160 | instance, left, right, top, bottom = applyMapTransforms(instance, left, right, top, bottom)
161 | mapData[id] = {left - right, top - bottom, left, top, instance = instance, name = data.name, mapType = data.mapType, parent = parent }
162 | else
163 | mapData[id] = {0, 0, 0, 0, instance = instance or -1, name = data.name, mapType = data.mapType, parent = parent }
164 | end
165 | end
166 |
167 | local function processMapChildrenRecursive(parent)
168 | local children = C_Map.GetMapChildrenInfo(parent)
169 | if children and #children > 0 then
170 | for i = 1, #children do
171 | local id = children[i].mapID
172 | if id and not mapData[id] then
173 | processMap(id, children[i], parent)
174 | processMapChildrenRecursive(id)
175 |
176 | -- process sibling maps (in the same group)
177 | -- in some cases these are not discovered by GetMapChildrenInfo above
178 | local groupID = C_Map.GetMapGroupID(id)
179 | if groupID then
180 | local groupMembers = C_Map.GetMapGroupMembersInfo(groupID)
181 | if groupMembers then
182 | for k = 1, #groupMembers do
183 | local memberId = groupMembers[k].mapID
184 | if memberId and not mapData[memberId] then
185 | processMap(memberId, C_Map.GetMapInfo(memberId), parent)
186 | processMapChildrenRecursive(memberId)
187 | end
188 | end
189 | end
190 | end
191 | end
192 | end
193 | end
194 | end
195 |
196 | local function fixupZones()
197 | local cosmic = C_Map.GetMapInfo(COSMIC_MAP_ID)
198 | if cosmic then
199 | mapData[COSMIC_MAP_ID] = {0, 0, 0, 0}
200 | mapData[COSMIC_MAP_ID].instance = -1
201 | mapData[COSMIC_MAP_ID].name = cosmic.name
202 | mapData[COSMIC_MAP_ID].mapType = cosmic.mapType
203 | end
204 |
205 | -- data for the azeroth world map
206 | if WoWClassic then
207 | worldMapData[0] = { 44688.53, 29795.11, 32601.04, 9894.93 }
208 | worldMapData[1] = { 44878.66, 29916.10, 8723.96, 14824.53 }
209 | elseif WoWBC then
210 | worldMapData[0] = { 44688.53, 29791.24, 32681.47, 11479.44 }
211 | worldMapData[1] = { 44878.66, 29916.10, 8723.96, 14824.53 }
212 | else
213 | worldMapData[0] = { 76153.14, 50748.62, 65008.24, 23827.51 }
214 | worldMapData[1] = { 77803.77, 51854.98, 13157.6, 28030.61 }
215 | worldMapData[571] = { 71773.64, 50054.05, 36205.94, 12366.81 }
216 | worldMapData[870] = { 67710.54, 45118.08, 33565.89, 38020.67 }
217 | worldMapData[1220] = { 82758.64, 55151.28, 52943.46, 24484.72 }
218 | worldMapData[1642] = { 77933.3, 51988.91, 44262.36, 32835.1 }
219 | worldMapData[1643] = { 76060.47, 50696.96, 55384.8, 25774.35 }
220 | end
221 | end
222 |
223 | local function gatherMapData()
224 | processTransforms()
225 |
226 | -- find all maps in well known structures
227 | if WoWClassic then
228 | processMap(WORLD_MAP_ID)
229 | processMapChildrenRecursive(WORLD_MAP_ID)
230 | else
231 | processMapChildrenRecursive(COSMIC_MAP_ID)
232 | end
233 |
234 | fixupZones()
235 |
236 | -- try to fill in holes in the map list
237 | for i = 1, 2000 do
238 | if not mapData[i] then
239 | local mapInfo = C_Map.GetMapInfo(i)
240 | if mapInfo and mapInfo.name then
241 | processMap(i, mapInfo, nil)
242 | end
243 | end
244 | end
245 | end
246 |
247 | gatherMapData()
248 | end
249 |
250 | -- Transform a set of coordinates based on the defined map transformations
251 | local function applyCoordinateTransforms(x, y, instanceID)
252 | if transforms[instanceID] then
253 | for _, transformData in ipairs(transforms[instanceID]) do
254 | if transformData.minX <= x and transformData.maxX >= x and transformData.minY <= y and transformData.maxY >= y then
255 | instanceID = transformData.newInstanceID
256 | x = x + transformData.offsetX
257 | y = y + transformData.offsetY
258 | break
259 | end
260 | end
261 | end
262 | return x, y, overrideInstance(instanceID)
263 | end
264 |
265 | local StartUpdateTimer
266 | local function UpdateCurrentPosition(instanceCheck)
267 | -- retrieve current zone
268 | local uiMapID = C_Map.GetBestMapForUnit("player")
269 |
270 | -- try to override the instance if possible
271 | if instanceCheck then
272 | local _x, _y, instance = HereBeDragons:GetPlayerWorldPosition()
273 | if instance and instance ~= -1 and mapData[uiMapID] and mapData[uiMapID].instance ~= instance and uiMapID ~= -1 and not instanceIDOverrides[instance] and not instanceIDOverrides[mapData[uiMapID].instance] then
274 | dynamicInstanceIDOverrides[instance] = mapData[uiMapID].instance
275 | end
276 | end
277 |
278 | if uiMapID ~= currentPlayerUIMapID then
279 | -- update location upvalues
280 | currentPlayerUIMapID, currentPlayerUIMapType = uiMapID, mapData[uiMapID] and mapData[uiMapID].mapType or 0
281 |
282 | -- signal callback
283 | HereBeDragons.callbacks:Fire("PlayerZoneChanged", currentPlayerUIMapID, currentPlayerUIMapType)
284 | end
285 |
286 | -- start a timer to update in micro dungeons since multi-level micro dungeons do not reliably fire events
287 | if currentPlayerUIMapType == Enum.UIMapType.Micro then
288 | StartUpdateTimer()
289 | end
290 | end
291 |
292 | -- upgradeable timer callback, don't want to keep calling the old function if the library is upgraded
293 | HereBeDragons.UpdateCurrentPosition = UpdateCurrentPosition
294 | local function UpdateTimerCallback()
295 | -- signal that the timer ran
296 | HereBeDragons.updateTimerActive = nil
297 |
298 | -- run update now
299 | HereBeDragons.UpdateCurrentPosition()
300 | end
301 |
302 | function StartUpdateTimer()
303 | if not HereBeDragons.updateTimerActive then
304 | -- prevent running multiple timers
305 | HereBeDragons.updateTimerActive = true
306 |
307 | -- and queue an update
308 | C_Timer.After(1, UpdateTimerCallback)
309 | end
310 | end
311 |
312 | local function OnEvent(frame, event, ...)
313 | UpdateCurrentPosition(true)
314 | end
315 |
316 | HereBeDragons.eventFrame:SetScript("OnEvent", OnEvent)
317 | HereBeDragons.eventFrame:UnregisterAllEvents()
318 | HereBeDragons.eventFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
319 | HereBeDragons.eventFrame:RegisterEvent("ZONE_CHANGED")
320 | HereBeDragons.eventFrame:RegisterEvent("ZONE_CHANGED_INDOORS")
321 | HereBeDragons.eventFrame:RegisterEvent("NEW_WMO_CHUNK")
322 | HereBeDragons.eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
323 |
324 | -- if we're loading after entering the world (ie. on demand), update position now
325 | if IsLoggedIn() then
326 | UpdateCurrentPosition(true)
327 | end
328 |
329 | --- Return the localized zone name for a given uiMapID
330 | -- @param uiMapID uiMapID of the zone
331 | function HereBeDragons:GetLocalizedMap(uiMapID)
332 | return mapData[uiMapID] and mapData[uiMapID].name or nil
333 | end
334 |
335 | --- Get the size of the zone
336 | -- @param uiMapID uiMapID of the zone
337 | -- @return width, height of the zone, in yards
338 | function HereBeDragons:GetZoneSize(uiMapID)
339 | local data = mapData[uiMapID]
340 | if not data then return 0, 0 end
341 |
342 | return data[1], data[2]
343 | end
344 |
345 | --- Get a list of all map IDs
346 | -- @return array-style table with all known/valid map IDs
347 | function HereBeDragons:GetAllMapIDs()
348 | local t = {}
349 | for id in pairs(mapData) do
350 | table.insert(t, id)
351 | end
352 | return t
353 | end
354 |
355 | --- Convert local/point coordinates to world coordinates in yards
356 | -- @param x X position in 0-1 point coordinates
357 | -- @param y Y position in 0-1 point coordinates
358 | -- @param zone uiMapID of the zone
359 | function HereBeDragons:GetWorldCoordinatesFromZone(x, y, zone)
360 | local data = mapData[zone]
361 | if not data or data[1] == 0 or data[2] == 0 then return nil, nil, nil end
362 | if not x or not y then return nil, nil, nil end
363 |
364 | local width, height, left, top = data[1], data[2], data[3], data[4]
365 | x, y = left - width * x, top - height * y
366 |
367 | return x, y, overrideInstance(data.instance)
368 | end
369 |
370 | --- Convert local/point coordinates to world coordinates in yards. The coordinates have to come from the Azeroth World Map
371 | -- @param x X position in 0-1 point coordinates
372 | -- @param y Y position in 0-1 point coordinates
373 | -- @param instance Instance to use for the world coordinates
374 | function HereBeDragons:GetWorldCoordinatesFromAzerothWorldMap(x, y, instance)
375 | local data = worldMapData[instance]
376 | if not data or data[1] == 0 or data[2] == 0 then return nil, nil, nil end
377 | if not x or not y then return nil, nil, nil end
378 |
379 | local width, height, left, top = data[1], data[2], data[3], data[4]
380 | x, y = left - width * x, top - height * y
381 |
382 | return x, y, instance
383 | end
384 |
385 |
386 | --- Convert world coordinates to local/point zone coordinates
387 | -- @param x Global X position
388 | -- @param y Global Y position
389 | -- @param zone uiMapID of the zone
390 | -- @param allowOutOfBounds Allow coordinates to go beyond the current map (ie. outside of the 0-1 range), otherwise nil will be returned
391 | function HereBeDragons:GetZoneCoordinatesFromWorld(x, y, zone, allowOutOfBounds)
392 | local data = mapData[zone]
393 | if not data or data[1] == 0 or data[2] == 0 then return nil, nil end
394 | if not x or not y then return nil, nil end
395 |
396 | local width, height, left, top = data[1], data[2], data[3], data[4]
397 | x, y = (left - x) / width, (top - y) / height
398 |
399 | -- verify the coordinates fall into the zone
400 | if not allowOutOfBounds and (x < 0 or x > 1 or y < 0 or y > 1) then return nil, nil end
401 |
402 | return x, y
403 | end
404 |
405 | --- Convert world coordinates to local/point zone coordinates on the azeroth world map
406 | -- @param x Global X position
407 | -- @param y Global Y position
408 | -- @param instance Instance to translate coordinates from
409 | -- @param allowOutOfBounds Allow coordinates to go beyond the current map (ie. outside of the 0-1 range), otherwise nil will be returned
410 | function HereBeDragons:GetAzerothWorldMapCoordinatesFromWorld(x, y, instance, allowOutOfBounds)
411 | local data = worldMapData[instance]
412 | if not data or data[1] == 0 or data[2] == 0 then return nil, nil end
413 | if not x or not y then return nil, nil end
414 |
415 | local width, height, left, top = data[1], data[2], data[3], data[4]
416 | x, y = (left - x) / width, (top - y) / height
417 |
418 | -- verify the coordinates fall into the zone
419 | if not allowOutOfBounds and (x < 0 or x > 1 or y < 0 or y > 1) then return nil, nil end
420 |
421 | return x, y
422 | end
423 |
424 | -- Helper function to handle world map coordinate translation
425 | local function TranslateAzerothWorldMapCoordinates(self, x, y, oZone, dZone, allowOutOfBounds)
426 | if (oZone ~= WORLD_MAP_ID and not mapData[oZone]) or (dZone ~= WORLD_MAP_ID and not mapData[dZone]) then return nil, nil end
427 | -- determine the instance we're working with
428 | local instance = overrideInstance((oZone == WORLD_MAP_ID) and mapData[dZone].instance or mapData[oZone].instance)
429 | if not worldMapData[instance] then return nil, nil end
430 |
431 | if oZone == WORLD_MAP_ID then
432 | x, y = self:GetWorldCoordinatesFromAzerothWorldMap(x, y, instance)
433 | return self:GetZoneCoordinatesFromWorld(x, y, dZone, allowOutOfBounds)
434 | else
435 | x, y = self:GetWorldCoordinatesFromZone(x, y, oZone)
436 | return self:GetAzerothWorldMapCoordinatesFromWorld(x, y, instance, allowOutOfBounds)
437 | end
438 | end
439 |
440 | --- Translate zone coordinates from one zone to another
441 | -- @param x X position in 0-1 point coordinates, relative to the origin zone
442 | -- @param y Y position in 0-1 point coordinates, relative to the origin zone
443 | -- @param oZone Origin Zone, uiMapID
444 | -- @param dZone Destination Zone, uiMapID
445 | -- @param allowOutOfBounds Allow coordinates to go beyond the current map (ie. outside of the 0-1 range), otherwise nil will be returned
446 | function HereBeDragons:TranslateZoneCoordinates(x, y, oZone, dZone, allowOutOfBounds)
447 | if oZone == dZone then return x, y end
448 |
449 | if oZone == WORLD_MAP_ID or dZone == WORLD_MAP_ID then
450 | return TranslateAzerothWorldMapCoordinates(self, x, y, oZone, dZone, allowOutOfBounds)
451 | end
452 |
453 | local xCoord, yCoord, instance = self:GetWorldCoordinatesFromZone(x, y, oZone)
454 | if not xCoord then return nil, nil end
455 |
456 | local data = mapData[dZone]
457 | if not data or overrideInstance(data.instance) ~= instance then return nil, nil end
458 |
459 | return self:GetZoneCoordinatesFromWorld(xCoord, yCoord, dZone, allowOutOfBounds)
460 | end
461 |
462 | --- Return the distance from an origin position to a destination position in the same instance/continent.
463 | -- @param instanceID instance ID
464 | -- @param oX origin X
465 | -- @param oY origin Y
466 | -- @param dX destination X
467 | -- @param dY destination Y
468 | -- @return distance, deltaX, deltaY
469 | function HereBeDragons:GetWorldDistance(instanceID, oX, oY, dX, dY)
470 | if not oX or not oY or not dX or not dY then return nil, nil, nil end
471 | local deltaX, deltaY = dX - oX, dY - oY
472 | return (deltaX * deltaX + deltaY * deltaY)^0.5, deltaX, deltaY
473 | end
474 |
475 | --- Return the distance between two points on the same continent
476 | -- @param oZone origin zone uiMapID
477 | -- @param oX origin X, in local zone/point coordinates
478 | -- @param oY origin Y, in local zone/point coordinates
479 | -- @param dZone destination zone uiMapID
480 | -- @param dX destination X, in local zone/point coordinates
481 | -- @param dY destination Y, in local zone/point coordinates
482 | -- @return distance, deltaX, deltaY in yards
483 | function HereBeDragons:GetZoneDistance(oZone, oX, oY, dZone, dX, dY)
484 | local oInstance, dInstance
485 | oX, oY, oInstance = self:GetWorldCoordinatesFromZone(oX, oY, oZone)
486 | if not oX then return nil, nil, nil end
487 |
488 | -- translate dX, dY to the origin zone
489 | dX, dY, dInstance = self:GetWorldCoordinatesFromZone(dX, dY, dZone)
490 | if not dX then return nil, nil, nil end
491 |
492 | if oInstance ~= dInstance then return nil, nil, nil end
493 |
494 | return self:GetWorldDistance(oInstance, oX, oY, dX, dY)
495 | end
496 |
497 | --- Return the angle and distance from an origin position to a destination position in the same instance/continent.
498 | -- @param instanceID instance ID
499 | -- @param oX origin X
500 | -- @param oY origin Y
501 | -- @param dX destination X
502 | -- @param dY destination Y
503 | -- @return angle, distance where angle is in radians and distance in yards
504 | function HereBeDragons:GetWorldVector(instanceID, oX, oY, dX, dY)
505 | local distance, deltaX, deltaY = self:GetWorldDistance(instanceID, oX, oY, dX, dY)
506 | if not distance then return nil, nil end
507 |
508 | -- calculate the angle from deltaY and deltaX
509 | local angle = atan2(-deltaX, deltaY)
510 |
511 | -- normalize the angle
512 | if angle > 0 then
513 | angle = PI2 - angle
514 | else
515 | angle = -angle
516 | end
517 |
518 | return angle, distance
519 | end
520 |
521 | --- Get the current world position of the specified unit
522 | -- The position is transformed to the current continent, if applicable
523 | -- NOTE: The same restrictions as for the UnitPosition() API apply,
524 | -- which means a very limited set of unit ids will actually work.
525 | -- @param unitId Unit Id
526 | -- @return x, y, instanceID
527 | function HereBeDragons:GetUnitWorldPosition(unitId)
528 | -- get the current position
529 | local y, x, _z, instanceID = UnitPosition(unitId)
530 | if not x or not y then return nil, nil, overrideInstance(instanceID) end
531 |
532 | -- return transformed coordinates
533 | return applyCoordinateTransforms(x, y, instanceID)
534 | end
535 |
536 | --- Get the current world position of the player
537 | -- The position is transformed to the current continent, if applicable
538 | -- @return x, y, instanceID
539 | function HereBeDragons:GetPlayerWorldPosition()
540 | -- get the current position
541 | local y, x, _z, instanceID = UnitPosition("player")
542 | if not x or not y then return nil, nil, overrideInstance(instanceID) end
543 |
544 | -- return transformed coordinates
545 | return applyCoordinateTransforms(x, y, instanceID)
546 | end
547 |
548 | --- Get the current zone and level of the player
549 | -- The returned mapFile can represent a micro dungeon, if the player currently is inside one.
550 | -- @return uiMapID, mapType
551 | function HereBeDragons:GetPlayerZone()
552 | return currentPlayerUIMapID, currentPlayerUIMapType
553 | end
554 |
555 | --- Get the current position of the player on a zone level
556 | -- The returned values are local point coordinates, 0-1. The mapFile can represent a micro dungeon.
557 | -- @param allowOutOfBounds Allow coordinates to go beyond the current map (ie. outside of the 0-1 range), otherwise nil will be returned
558 | -- @return x, y, uiMapID, mapType
559 | function HereBeDragons:GetPlayerZonePosition(allowOutOfBounds)
560 | if not currentPlayerUIMapID then return nil, nil, nil, nil end
561 | local x, y, _instanceID = self:GetPlayerWorldPosition()
562 | if not x or not y then return nil, nil, nil, nil end
563 |
564 | x, y = self:GetZoneCoordinatesFromWorld(x, y, currentPlayerUIMapID, allowOutOfBounds)
565 | if x and y then
566 | return x, y, currentPlayerUIMapID, currentPlayerUIMapType
567 | end
568 | return nil, nil, nil, nil
569 | end
570 |
--------------------------------------------------------------------------------
/Libraries/LibDBIcon-1.0/LibDBIcon-1.0.lua:
--------------------------------------------------------------------------------
1 |
2 | -----------------------------------------------------------------------
3 | -- LibDBIcon-1.0
4 | --
5 | -- Allows addons to easily create a lightweight minimap icon as an alternative to heavier LDB displays.
6 | --
7 |
8 | local DBICON10 = "LibDBIcon-1.0"
9 | local DBICON10_MINOR = 44 -- Bump on changes
10 | if not LibStub then error(DBICON10 .. " requires LibStub.") end
11 | local ldb = LibStub("LibDataBroker-1.1", true)
12 | if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end
13 | local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR)
14 | if not lib then return end
15 |
16 | lib.objects = lib.objects or {}
17 | lib.callbackRegistered = lib.callbackRegistered or nil
18 | lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
19 | lib.notCreated = lib.notCreated or {}
20 | lib.radius = lib.radius or 5
21 | local next, Minimap, CreateFrame = next, Minimap, CreateFrame
22 | lib.tooltip = lib.tooltip or CreateFrame("GameTooltip", "LibDBIconTooltip", UIParent, "GameTooltipTemplate")
23 | local isDraggingButton = false
24 |
25 | function lib:IconCallback(event, name, key, value)
26 | if lib.objects[name] then
27 | if key == "icon" then
28 | lib.objects[name].icon:SetTexture(value)
29 | elseif key == "iconCoords" then
30 | lib.objects[name].icon:UpdateCoord()
31 | elseif key == "iconR" then
32 | local _, g, b = lib.objects[name].icon:GetVertexColor()
33 | lib.objects[name].icon:SetVertexColor(value, g, b)
34 | elseif key == "iconG" then
35 | local r, _, b = lib.objects[name].icon:GetVertexColor()
36 | lib.objects[name].icon:SetVertexColor(r, value, b)
37 | elseif key == "iconB" then
38 | local r, g = lib.objects[name].icon:GetVertexColor()
39 | lib.objects[name].icon:SetVertexColor(r, g, value)
40 | end
41 | end
42 | end
43 | if not lib.callbackRegistered then
44 | ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback")
45 | ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback")
46 | ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconR", "IconCallback")
47 | ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconG", "IconCallback")
48 | ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconB", "IconCallback")
49 | lib.callbackRegistered = true
50 | end
51 |
52 | local function getAnchors(frame)
53 | local x, y = frame:GetCenter()
54 | if not x or not y then return "CENTER" end
55 | local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or ""
56 | local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM"
57 | return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf
58 | end
59 |
60 | local function onEnter(self)
61 | if isDraggingButton then return end
62 |
63 | for _, button in next, lib.objects do
64 | if button.showOnMouseover then
65 | button.fadeOut:Stop()
66 | button:SetAlpha(1)
67 | end
68 | end
69 |
70 | local obj = self.dataObject
71 | if obj.OnTooltipShow then
72 | lib.tooltip:SetOwner(self, "ANCHOR_NONE")
73 | lib.tooltip:SetPoint(getAnchors(self))
74 | obj.OnTooltipShow(lib.tooltip)
75 | lib.tooltip:Show()
76 | elseif obj.OnEnter then
77 | obj.OnEnter(self)
78 | end
79 | end
80 |
81 | local function onLeave(self)
82 | lib.tooltip:Hide()
83 |
84 | if not isDraggingButton then
85 | for _, button in next, lib.objects do
86 | if button.showOnMouseover then
87 | button.fadeOut:Play()
88 | end
89 | end
90 | end
91 |
92 | local obj = self.dataObject
93 | if obj.OnLeave then
94 | obj.OnLeave(self)
95 | end
96 | end
97 |
98 | --------------------------------------------------------------------------------
99 |
100 | local onDragStart, updatePosition
101 |
102 | do
103 | local minimapShapes = {
104 | ["ROUND"] = {true, true, true, true},
105 | ["SQUARE"] = {false, false, false, false},
106 | ["CORNER-TOPLEFT"] = {false, false, false, true},
107 | ["CORNER-TOPRIGHT"] = {false, false, true, false},
108 | ["CORNER-BOTTOMLEFT"] = {false, true, false, false},
109 | ["CORNER-BOTTOMRIGHT"] = {true, false, false, false},
110 | ["SIDE-LEFT"] = {false, true, false, true},
111 | ["SIDE-RIGHT"] = {true, false, true, false},
112 | ["SIDE-TOP"] = {false, false, true, true},
113 | ["SIDE-BOTTOM"] = {true, true, false, false},
114 | ["TRICORNER-TOPLEFT"] = {false, true, true, true},
115 | ["TRICORNER-TOPRIGHT"] = {true, false, true, true},
116 | ["TRICORNER-BOTTOMLEFT"] = {true, true, false, true},
117 | ["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false},
118 | }
119 |
120 | local rad, cos, sin, sqrt, max, min = math.rad, math.cos, math.sin, math.sqrt, math.max, math.min
121 | function updatePosition(button, position)
122 | local angle = rad(position or 225)
123 | local x, y, q = cos(angle), sin(angle), 1
124 | if x < 0 then q = q + 1 end
125 | if y > 0 then q = q + 2 end
126 | local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND"
127 | local quadTable = minimapShapes[minimapShape]
128 | local w = (Minimap:GetWidth() / 2) + lib.radius
129 | local h = (Minimap:GetHeight() / 2) + lib.radius
130 | if quadTable[q] then
131 | x, y = x*w, y*h
132 | else
133 | local diagRadiusW = sqrt(2*(w)^2)-10
134 | local diagRadiusH = sqrt(2*(h)^2)-10
135 | x = max(-w, min(x*diagRadiusW, w))
136 | y = max(-h, min(y*diagRadiusH, h))
137 | end
138 | button:SetPoint("CENTER", Minimap, "CENTER", x, y)
139 | end
140 | end
141 |
142 | local function onClick(self, b)
143 | if self.dataObject.OnClick then
144 | self.dataObject.OnClick(self, b)
145 | end
146 | end
147 |
148 | local function onMouseDown(self)
149 | self.isMouseDown = true
150 | self.icon:UpdateCoord()
151 | end
152 |
153 | local function onMouseUp(self)
154 | self.isMouseDown = false
155 | self.icon:UpdateCoord()
156 | end
157 |
158 | do
159 | local deg, atan2 = math.deg, math.atan2
160 | local function onUpdate(self)
161 | local mx, my = Minimap:GetCenter()
162 | local px, py = GetCursorPosition()
163 | local scale = Minimap:GetEffectiveScale()
164 | px, py = px / scale, py / scale
165 | local pos = 225
166 | if self.db then
167 | pos = deg(atan2(py - my, px - mx)) % 360
168 | self.db.minimapPos = pos
169 | else
170 | pos = deg(atan2(py - my, px - mx)) % 360
171 | self.minimapPos = pos
172 | end
173 | updatePosition(self, pos)
174 | end
175 |
176 | function onDragStart(self)
177 | self:LockHighlight()
178 | self.isMouseDown = true
179 | self.icon:UpdateCoord()
180 | self:SetScript("OnUpdate", onUpdate)
181 | isDraggingButton = true
182 | lib.tooltip:Hide()
183 | for _, button in next, lib.objects do
184 | if button.showOnMouseover then
185 | button.fadeOut:Stop()
186 | button:SetAlpha(1)
187 | end
188 | end
189 | end
190 | end
191 |
192 | local function onDragStop(self)
193 | self:SetScript("OnUpdate", nil)
194 | self.isMouseDown = false
195 | self.icon:UpdateCoord()
196 | self:UnlockHighlight()
197 | isDraggingButton = false
198 | for _, button in next, lib.objects do
199 | if button.showOnMouseover then
200 | button.fadeOut:Play()
201 | end
202 | end
203 | end
204 |
205 | local defaultCoords = {0, 1, 0, 1}
206 | local function updateCoord(self)
207 | local coords = self:GetParent().dataObject.iconCoords or defaultCoords
208 | local deltaX, deltaY = 0, 0
209 | if not self:GetParent().isMouseDown then
210 | deltaX = (coords[2] - coords[1]) * 0.05
211 | deltaY = (coords[4] - coords[3]) * 0.05
212 | end
213 | self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY)
214 | end
215 |
216 | local function createButton(name, object, db)
217 | local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap)
218 | button.dataObject = object
219 | button.db = db
220 | button:SetFrameStrata("MEDIUM")
221 | if button.SetFixedFrameStrata then -- Classic support
222 | button:SetFixedFrameStrata(true)
223 | end
224 | button:SetFrameLevel(8)
225 | if button.SetFixedFrameLevel then -- Classic support
226 | button:SetFixedFrameLevel(true)
227 | end
228 | button:SetSize(31, 31)
229 | button:RegisterForClicks("anyUp")
230 | button:RegisterForDrag("LeftButton")
231 | button:SetHighlightTexture(136477) --"Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight"
232 | local overlay = button:CreateTexture(nil, "OVERLAY")
233 | overlay:SetSize(53, 53)
234 | overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder"
235 | overlay:SetPoint("TOPLEFT")
236 | local background = button:CreateTexture(nil, "BACKGROUND")
237 | background:SetSize(20, 20)
238 | background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background"
239 | background:SetPoint("TOPLEFT", 7, -5)
240 | local icon = button:CreateTexture(nil, "ARTWORK")
241 | icon:SetSize(17, 17)
242 | icon:SetTexture(object.icon)
243 | icon:SetPoint("TOPLEFT", 7, -6)
244 | button.icon = icon
245 | button.isMouseDown = false
246 |
247 | local r, g, b = icon:GetVertexColor()
248 | icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b)
249 |
250 | icon.UpdateCoord = updateCoord
251 | icon:UpdateCoord()
252 |
253 | button:SetScript("OnEnter", onEnter)
254 | button:SetScript("OnLeave", onLeave)
255 | button:SetScript("OnClick", onClick)
256 | if not db or not db.lock then
257 | button:SetScript("OnDragStart", onDragStart)
258 | button:SetScript("OnDragStop", onDragStop)
259 | end
260 | button:SetScript("OnMouseDown", onMouseDown)
261 | button:SetScript("OnMouseUp", onMouseUp)
262 |
263 | button.fadeOut = button:CreateAnimationGroup()
264 | local animOut = button.fadeOut:CreateAnimation("Alpha")
265 | animOut:SetOrder(1)
266 | animOut:SetDuration(0.2)
267 | animOut:SetFromAlpha(1)
268 | animOut:SetToAlpha(0)
269 | animOut:SetStartDelay(1)
270 | button.fadeOut:SetToFinalAlpha(true)
271 |
272 | lib.objects[name] = button
273 |
274 | if lib.loggedIn then
275 | updatePosition(button, db and db.minimapPos)
276 | if not db or not db.hide then
277 | button:Show()
278 | else
279 | button:Hide()
280 | end
281 | end
282 | lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback
283 | end
284 |
285 | -- We could use a metatable.__index on lib.objects, but then we'd create
286 | -- the icons when checking things like :IsRegistered, which is not necessary.
287 | local function check(name)
288 | if lib.notCreated[name] then
289 | createButton(name, lib.notCreated[name][1], lib.notCreated[name][2])
290 | lib.notCreated[name] = nil
291 | end
292 | end
293 |
294 | -- Wait a bit with the initial positioning to let any GetMinimapShape addons
295 | -- load up.
296 | if not lib.loggedIn then
297 | local f = CreateFrame("Frame")
298 | f:SetScript("OnEvent", function(f)
299 | for _, button in next, lib.objects do
300 | updatePosition(button, button.db and button.db.minimapPos)
301 | if not button.db or not button.db.hide then
302 | button:Show()
303 | else
304 | button:Hide()
305 | end
306 | end
307 | lib.loggedIn = true
308 | f:SetScript("OnEvent", nil)
309 | end)
310 | f:RegisterEvent("PLAYER_LOGIN")
311 | end
312 |
313 | local function getDatabase(name)
314 | return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db
315 | end
316 |
317 | function lib:Register(name, object, db)
318 | if not object.icon then error("Can't register LDB objects without icons set!") end
319 | if lib.objects[name] or lib.notCreated[name] then error(DBICON10.. ": Object '".. name .."' is already registered.") end
320 | if not db or not db.hide then
321 | createButton(name, object, db)
322 | else
323 | lib.notCreated[name] = {object, db}
324 | end
325 | end
326 |
327 | function lib:Lock(name)
328 | if not lib:IsRegistered(name) then return end
329 | if lib.objects[name] then
330 | lib.objects[name]:SetScript("OnDragStart", nil)
331 | lib.objects[name]:SetScript("OnDragStop", nil)
332 | end
333 | local db = getDatabase(name)
334 | if db then
335 | db.lock = true
336 | end
337 | end
338 |
339 | function lib:Unlock(name)
340 | if not lib:IsRegistered(name) then return end
341 | if lib.objects[name] then
342 | lib.objects[name]:SetScript("OnDragStart", onDragStart)
343 | lib.objects[name]:SetScript("OnDragStop", onDragStop)
344 | end
345 | local db = getDatabase(name)
346 | if db then
347 | db.lock = nil
348 | end
349 | end
350 |
351 | function lib:Hide(name)
352 | if not lib.objects[name] then return end
353 | lib.objects[name]:Hide()
354 | end
355 |
356 | function lib:Show(name)
357 | check(name)
358 | local button = lib.objects[name]
359 | if button then
360 | button:Show()
361 | updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
362 | end
363 | end
364 |
365 | function lib:IsRegistered(name)
366 | return (lib.objects[name] or lib.notCreated[name]) and true or false
367 | end
368 |
369 | function lib:Refresh(name, db)
370 | check(name)
371 | local button = lib.objects[name]
372 | if db then
373 | button.db = db
374 | end
375 | updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
376 | if not button.db or not button.db.hide then
377 | button:Show()
378 | else
379 | button:Hide()
380 | end
381 | if not button.db or not button.db.lock then
382 | button:SetScript("OnDragStart", onDragStart)
383 | button:SetScript("OnDragStop", onDragStop)
384 | else
385 | button:SetScript("OnDragStart", nil)
386 | button:SetScript("OnDragStop", nil)
387 | end
388 | end
389 |
390 | function lib:GetMinimapButton(name)
391 | return lib.objects[name]
392 | end
393 |
394 | do
395 | local function OnMinimapEnter()
396 | if isDraggingButton then return end
397 | for _, button in next, lib.objects do
398 | if button.showOnMouseover then
399 | button.fadeOut:Stop()
400 | button:SetAlpha(1)
401 | end
402 | end
403 | end
404 | local function OnMinimapLeave()
405 | if isDraggingButton then return end
406 | for _, button in next, lib.objects do
407 | if button.showOnMouseover then
408 | button.fadeOut:Play()
409 | end
410 | end
411 | end
412 | Minimap:HookScript("OnEnter", OnMinimapEnter)
413 | Minimap:HookScript("OnLeave", OnMinimapLeave)
414 |
415 | function lib:ShowOnEnter(name, value)
416 | local button = lib.objects[name]
417 | if button then
418 | if value then
419 | button.showOnMouseover = true
420 | button.fadeOut:Stop()
421 | button:SetAlpha(0)
422 | else
423 | button.showOnMouseover = false
424 | button.fadeOut:Stop()
425 | button:SetAlpha(1)
426 | end
427 | end
428 | end
429 | end
430 |
431 | function lib:GetButtonList()
432 | local t = {}
433 | for name in next, lib.objects do
434 | t[#t+1] = name
435 | end
436 | return t
437 | end
438 |
439 | function lib:SetButtonRadius(radius)
440 | if type(radius) == "number" then
441 | lib.radius = radius
442 | for _, button in next, lib.objects do
443 | updatePosition(button, button.db and button.db.minimapPos or button.minimapPos)
444 | end
445 | end
446 | end
447 |
448 | function lib:SetButtonToPosition(button, position)
449 | updatePosition(lib.objects[button] or button, position)
450 | end
451 |
452 | -- Upgrade!
453 | for name, button in next, lib.objects do
454 | local db = getDatabase(name)
455 | if not db or not db.lock then
456 | button:SetScript("OnDragStart", onDragStart)
457 | button:SetScript("OnDragStop", onDragStop)
458 | end
459 | button:SetScript("OnEnter", onEnter)
460 | button:SetScript("OnLeave", onLeave)
461 | button:SetScript("OnClick", onClick)
462 | button:SetScript("OnMouseDown", onMouseDown)
463 | button:SetScript("OnMouseUp", onMouseUp)
464 |
465 | if not button.fadeOut then -- Upgrade to 39
466 | button.fadeOut = button:CreateAnimationGroup()
467 | local animOut = button.fadeOut:CreateAnimation("Alpha")
468 | animOut:SetOrder(1)
469 | animOut:SetDuration(0.2)
470 | animOut:SetFromAlpha(1)
471 | animOut:SetToAlpha(0)
472 | animOut:SetStartDelay(1)
473 | button.fadeOut:SetToFinalAlpha(true)
474 | end
475 | end
476 | lib:SetButtonRadius(lib.radius) -- Upgrade to 40
477 |
--------------------------------------------------------------------------------
/Libraries/LibDataBroker-1.1/LibDataBroker-1.1.lua:
--------------------------------------------------------------------------------
1 |
2 | assert(LibStub, "LibDataBroker-1.1 requires LibStub")
3 | assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
4 |
5 | local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
6 | if not lib then return end
7 | oldminor = oldminor or 0
8 |
9 |
10 | lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
11 | lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
12 | local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
13 |
14 | if oldminor < 2 then
15 | lib.domt = {
16 | __metatable = "access denied",
17 | __index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
18 | }
19 | end
20 |
21 | if oldminor < 3 then
22 | lib.domt.__newindex = function(self, key, value)
23 | if not attributestorage[self] then attributestorage[self] = {} end
24 | if attributestorage[self][key] == value then return end
25 | attributestorage[self][key] = value
26 | local name = namestorage[self]
27 | if not name then return end
28 | callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
29 | callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
30 | callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
31 | callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
32 | end
33 | end
34 |
35 | if oldminor < 2 then
36 | function lib:NewDataObject(name, dataobj)
37 | if self.proxystorage[name] then return end
38 |
39 | if dataobj then
40 | assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
41 | self.attributestorage[dataobj] = {}
42 | for i,v in pairs(dataobj) do
43 | self.attributestorage[dataobj][i] = v
44 | dataobj[i] = nil
45 | end
46 | end
47 | dataobj = setmetatable(dataobj or {}, self.domt)
48 | self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
49 | self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
50 | return dataobj
51 | end
52 | end
53 |
54 | if oldminor < 1 then
55 | function lib:DataObjectIterator()
56 | return pairs(self.proxystorage)
57 | end
58 |
59 | function lib:GetDataObjectByName(dataobjectname)
60 | return self.proxystorage[dataobjectname]
61 | end
62 |
63 | function lib:GetNameByDataObject(dataobject)
64 | return self.namestorage[dataobject]
65 | end
66 | end
67 |
68 | if oldminor < 4 then
69 | local next = pairs(attributestorage)
70 | function lib:pairs(dataobject_or_name)
71 | local t = type(dataobject_or_name)
72 | assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
73 |
74 | local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
75 | assert(attributestorage[dataobj], "Data object not found")
76 |
77 | return next, attributestorage[dataobj], nil
78 | end
79 |
80 | local ipairs_iter = ipairs(attributestorage)
81 | function lib:ipairs(dataobject_or_name)
82 | local t = type(dataobject_or_name)
83 | assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
84 |
85 | local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
86 | assert(attributestorage[dataobj], "Data object not found")
87 |
88 | return ipairs_iter, attributestorage[dataobj], 0
89 | end
90 | end
91 |
--------------------------------------------------------------------------------
/Libraries/LibStub/LibStub.lua:
--------------------------------------------------------------------------------
1 | -- $Id: LibStub.lua 103 2014-10-16 03:02:50Z mikk $
2 | -- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/addons/libstub/ for more info
3 | -- LibStub is hereby placed in the Public Domain
4 | -- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
5 | local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
6 | local LibStub = _G[LIBSTUB_MAJOR]
7 |
8 | -- Check to see is this version of the stub is obsolete
9 | if not LibStub or LibStub.minor < LIBSTUB_MINOR then
10 | LibStub = LibStub or {libs = {}, minors = {} }
11 | _G[LIBSTUB_MAJOR] = LibStub
12 | LibStub.minor = LIBSTUB_MINOR
13 |
14 | -- LibStub:NewLibrary(major, minor)
15 | -- major (string) - the major version of the library
16 | -- minor (string or number ) - the minor version of the library
17 | --
18 | -- returns nil if a newer or same version of the lib is already present
19 | -- returns empty library object or old library object if upgrade is needed
20 | function LibStub:NewLibrary(major, minor)
21 | assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
22 | minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
23 |
24 | local oldminor = self.minors[major]
25 | if oldminor and oldminor >= minor then return nil end
26 | self.minors[major], self.libs[major] = minor, self.libs[major] or {}
27 | return self.libs[major], oldminor
28 | end
29 |
30 | -- LibStub:GetLibrary(major, [silent])
31 | -- major (string) - the major version of the library
32 | -- silent (boolean) - if true, library is optional, silently return nil if its not found
33 | --
34 | -- throws an error if the library can not be found (except silent is set)
35 | -- returns the library object if found
36 | function LibStub:GetLibrary(major, silent)
37 | if not self.libs[major] and not silent then
38 | error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
39 | end
40 | return self.libs[major], self.minors[major]
41 | end
42 |
43 | -- LibStub:IterateLibraries()
44 | --
45 | -- Returns an iterator for the currently registered libraries
46 | function LibStub:IterateLibraries()
47 | return pairs(self.libs)
48 | end
49 |
50 | setmetatable(LibStub, { __call = LibStub.GetLibrary })
51 | end
52 |
--------------------------------------------------------------------------------
/Libraries/LibUIDropDownMenu/LibEasyMenu.lua:
--------------------------------------------------------------------------------
1 | --$Id: LibEasyMenu.lua 64 2020-11-18 13:13:15Z arithmandar $
2 | -- //////////////////////////////////////////////////////////////
3 | -- Notes:
4 | -- Functions have been moved to under LibUIDropDownMenu.lua
5 | -- New function calls are as below:
6 | --
7 | -- - lib:EasyMenu(menuList, menuFrame, anchor, x, y, displayMode, autoHideDelay )
8 | -- - lib:EasyMenu_Initialize( frame, level, menuList )
9 | --
10 | -- //////////////////////////////////////////////////////////////
11 | -- Simplified Menu Display System
12 | -- This is a basic system for displaying a menu from a structure table.
13 | --
14 | -- See UIDropDownMenu.lua for the menuList details.
15 | --
16 | -- Args:
17 | -- menuList - menu table
18 | -- menuFrame - the UI frame to populate
19 | -- anchor - where to anchor the frame (e.g. CURSOR)
20 | -- x - x offset
21 | -- y - y offset
22 | -- displayMode - border type
23 | -- autoHideDelay - how long until the menu disappears
24 | --
25 | --
26 | --[[
27 | function EasyMenu(menuList, menuFrame, anchor, x, y, displayMode, autoHideDelay )
28 | if ( displayMode == "MENU" ) then
29 | menuFrame.displayMode = displayMode;
30 | end
31 | UIDropDownMenu_Initialize(menuFrame, EasyMenu_Initialize, displayMode, nil, menuList);
32 | ToggleDropDownMenu(1, nil, menuFrame, anchor, x, y, menuList, nil, autoHideDelay);
33 | end
34 |
35 | function EasyMenu_Initialize( frame, level, menuList )
36 | for index = 1, #menuList do
37 | local value = menuList[index]
38 | if (value.text) then
39 | value.index = index;
40 | UIDropDownMenu_AddButton( value, level );
41 | end
42 | end
43 | end
44 | ]]
45 |
--------------------------------------------------------------------------------
/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
24 |
25 |
--------------------------------------------------------------------------------
/Libraries/LibUIDropDownMenu/LibUIDropDownMenuTemplates.lua:
--------------------------------------------------------------------------------
1 | -- $Id: LibUIDropDownMenuTemplates.lua 64 2020-11-18 13:13:15Z arithmandar $
2 | -- ----------------------------------------------------------------------------
3 | -- Localized Lua globals.
4 | -- ----------------------------------------------------------------------------
5 | --[[local _G = getfenv(0)
6 | -- ----------------------------------------------------------------------------
7 | local MAJOR_VERSION = "LibUIDropDownMenuTemplates-3.0"
8 | local MINOR_VERSION = 90000 + tonumber(("$Rev: 64 $"):match("%d+"))
9 |
10 | local LibStub = _G.LibStub
11 | if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end
12 | local Lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
13 | if not Lib then return end
14 |
15 | -- Custom dropdown buttons are instantiated by some external system.
16 | -- When calling L_UIDropDownMenu_AddButton that system sets info.customFrame to the instance of the frame it wants to place on the menu.
17 | -- The dropdown menu creates its button for the entry as it normally would, but hides all elements. The custom frame is then anchored
18 | -- to that button and assumes responsibility for all relevant dropdown menu operations.
19 | -- The hidden button will request a size that it should become from the custom frame.
20 |
21 | L_DropDownMenuButtonMixin = {}
22 |
23 | function L_DropDownMenuButtonMixin:OnEnter(...)
24 | ExecuteFrameScript(self:GetParent(), "OnEnter", ...);
25 | end
26 |
27 | function L_DropDownMenuButtonMixin:OnLeave(...)
28 | ExecuteFrameScript(self:GetParent(), "OnLeave", ...);
29 | end
30 |
31 | function L_DropDownMenuButtonMixin:OnMouseDown(button)
32 | if self:IsEnabled() then
33 | L_ToggleDropDownMenu(nil, nil, self:GetParent());
34 | PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
35 | end
36 | end
37 |
38 | L_LargeDropDownMenuButtonMixin = CreateFromMixins(L_DropDownMenuButtonMixin);
39 |
40 | function L_LargeDropDownMenuButtonMixin:OnMouseDown(button)
41 | if self:IsEnabled() then
42 | local parent = self:GetParent();
43 | L_ToggleDropDownMenu(nil, nil, parent, parent, -8, 8);
44 | PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
45 | end
46 | end
47 |
48 | L_DropDownExpandArrowMixin = {};
49 |
50 | function L_DropDownExpandArrowMixin:OnEnter()
51 | local level = self:GetParent():GetParent():GetID() + 1;
52 |
53 | L_CloseDropDownMenus(level);
54 |
55 | if self:IsEnabled() then
56 | local listFrame = _G["L_DropDownList"..level];
57 | if ( not listFrame or not listFrame:IsShown() or select(2, listFrame:GetPoint()) ~= self ) then
58 | L_ToggleDropDownMenu(level, self:GetParent().value, nil, nil, nil, nil, self:GetParent().menuList, self);
59 | end
60 | end
61 | end
62 |
63 | function L_DropDownExpandArrowMixin:OnMouseDown(button)
64 | if self:IsEnabled() then
65 | L_ToggleDropDownMenu(self:GetParent():GetParent():GetID() + 1, self:GetParent().value, nil, nil, nil, nil, self:GetParent().menuList, self);
66 | end
67 | end
68 |
69 | L_UIDropDownCustomMenuEntryMixin = {};
70 |
71 | function L_UIDropDownCustomMenuEntryMixin:GetPreferredEntryWidth()
72 | -- NOTE: Only width is currently supported, dropdown menus size vertically based on how many buttons are present.
73 | return self:GetWidth();
74 | end
75 |
76 | function L_UIDropDownCustomMenuEntryMixin:OnSetOwningButton()
77 | -- for derived objects to implement
78 | end
79 |
80 | function L_UIDropDownCustomMenuEntryMixin:SetOwningButton(button)
81 | self:SetParent(button:GetParent());
82 | self.owningButton = button;
83 | self:OnSetOwningButton();
84 | end
85 |
86 | function L_UIDropDownCustomMenuEntryMixin:GetOwningDropdown()
87 | return self.owningButton:GetParent();
88 | end
89 |
90 | function L_UIDropDownCustomMenuEntryMixin:SetContextData(contextData)
91 | self.contextData = contextData;
92 | end
93 |
94 | function L_UIDropDownCustomMenuEntryMixin:GetContextData()
95 | return self.contextData;
96 | end
97 |
98 | -- //////////////////////////////////////////////////////////////
99 | -- L_UIDropDownCustomMenuEntryTemplate
100 | function L_Create_UIDropDownCustomMenuEntry(name, parent)
101 | local f = _G[name] or CreateFrame("Frame", name, parent or nil)
102 | f:EnableMouse(true)
103 | f:Hide()
104 |
105 | -- I am not 100% sure if below works for replacing the mixins
106 | f:SetScript("GetPreferredEntryWidth", function(self)
107 | return self:GetWidth()
108 | end)
109 | f:SetScript("SetOwningButton", function(self, button)
110 | self:SetParent(button:GetParent())
111 | self.owningButton = button
112 | self:OnSetOwningButton()
113 | end)
114 | f:SetScript("GetOwningDropdown", function(self)
115 | return self.owningButton:GetParent()
116 | end)
117 | f:SetScript("SetContextData", function(self, contextData)
118 | self.contextData = contextData
119 | end)
120 | f:SetScript("GetContextData", function(self)
121 | return self.contextData
122 | end)
123 |
124 | return f
125 | end
126 | ]]
127 |
--------------------------------------------------------------------------------
/Libraries/LibUIDropDownMenu/LibUIDropDownMenuTemplates.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
412 |
413 |
--------------------------------------------------------------------------------
/Media/Background/Background.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Background/Background.tga
--------------------------------------------------------------------------------
/Media/Background/Separator.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Background/Separator.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollDownButton-Disabled.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollDownButton-Disabled.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollDownButton-Down.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollDownButton-Down.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollDownButton-Highlight.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollDownButton-Highlight.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollDownButton-Up.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollDownButton-Up.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollLeftButton-Disabled.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollLeftButton-Disabled.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollLeftButton-Down.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollLeftButton-Down.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollLeftButton-Highlight.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollLeftButton-Highlight.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollLeftButton-Up.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollLeftButton-Up.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollRightButton-Disabled.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollRightButton-Disabled.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollRightButton-Down.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollRightButton-Down.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollRightButton-Highlight.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollRightButton-Highlight.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollRightButton-Up.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollRightButton-Up.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollUpButton-Disabled.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollUpButton-Disabled.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollUpButton-Down.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollUpButton-Down.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollUpButton-Highlight.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollUpButton-Highlight.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollUpButton-Up.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollUpButton-Up.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollbarHorizontal-Knob.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollbarHorizontal-Knob.tga
--------------------------------------------------------------------------------
/Media/Buttons/ScrollbarVertical-Knob.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/ScrollbarVertical-Knob.tga
--------------------------------------------------------------------------------
/Media/Buttons/SpellBackground.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Buttons/SpellBackground.tga
--------------------------------------------------------------------------------
/Media/Buttons/SpellHighlight.tga:
--------------------------------------------------------------------------------
1 | @ @ !!!!))))))))))))))))))))))))))))))))))))))))))))))))!!!! !1119!9!9!9!9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9!9!9!9!111! #
2 | #
3 | 11A%A%I*I*I*I*I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I*I*I*I*A%A%11#
4 | #
5 | #
6 | 1A%A%R0!R0!Z4!Z4!Z4!Z4!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z4!Z4!Z4!Z4!R0!R0!A%A%1#
7 | !!1A%R,Z1b6#b6#b8#b8#b8#Z4Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4b8#b8#b8#b6#b6#Z1R,A%1!!!11A%Z1b6#b6#k<)k<)b8#b8#b8#Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!b8#b8#b8#k<)k<)b6#b6#Z1A%11!!1A%R0!b6#b6#k<)k<)k<)b8#b8#Z4T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0Z4b8#b8#k<)k<)k<)b6#b6#R0!A%1!!1A%R0!b6#k<)k<)k<)b8#b8#Z4R0O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,R0Z4b8#b8#k<)k<)k<)b6#R0!A%1!)9!I*Z4!b8#k<)k<)b8#Z4!Z4!G)G)9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 G)G)Z4!Z4!b8#k<)k<)b8#Z4!I*9!))9!I*Z4!b8#b8#b8#b8#Z4!G)44+
+
+
+
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
+
+
+
+
44G)Z4!b8#b8#b8#b8#Z4!I*9!))9!I*Z4!b8#b8#b8#Z4G)44!
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | !44G)Z4b8#b8#b8#Z4!I*9!))9!I*Z4!Z4b8#Z4R0G)4!!!!4G)R0Z4b8#Z4Z4!I*9!))9 I(Z0!Z4!Z4!T0O,9 +
48 |
49 | +
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 +
50 |
51 | +
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 +
52 |
53 | +
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 +
54 |
55 | +
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
56 |
57 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
58 |
59 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
60 |
61 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
62 |
63 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
64 |
65 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
66 |
67 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
68 |
69 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
70 |
71 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
72 |
73 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
74 |
75 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
76 |
77 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
78 |
79 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
80 |
81 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
82 |
83 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
84 |
85 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
86 |
87 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
88 |
89 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
90 |
91 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
92 |
93 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
94 |
95 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
96 |
97 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
98 |
99 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
100 |
101 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
102 |
103 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
104 |
105 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
106 |
107 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
108 |
109 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
110 |
111 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
112 |
113 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
114 |
115 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
116 |
117 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 (
118 |
119 | (
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 +
120 |
121 | +
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 +
122 |
123 | +
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 +
124 |
125 | +
9 O,T0Z4!Z4!Z0!I(9 ))9 I(Z0!Z4!Z4!T0O,9 +
126 |
127 | +
9 O,T0Z4!Z4!Z0!I(9 ))9!I*Z4!Z4b8#Z4R0G)4!!!!4G)R0Z4b8#Z4Z4!I*9!))9!I*Z4!b8#b8#b8#Z4G)44!
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 | !44G)Z4b8#b8#b8#Z4!I*9!))9!I*Z4!b8#b8#b8#b8#Z4!G)44+
+
+
+
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
(
+
+
+
+
44G)Z4!b8#b8#b8#b8#Z4!I*9!))9!I*Z4!b8#k<)k<)b8#Z4!Z4!G)G)9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 G)G)Z4!Z4!b8#k<)k<)b8#Z4!I*9!)!1A%R0!b6#k<)k<)k<)b8#b8#Z4R0O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,R0Z4b8#b8#k<)k<)k<)b6#R0!A%1!!1A%R0!b6#b6#k<)k<)k<)b8#b8#Z4T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0T0Z4b8#b8#k<)k<)k<)b6#b6#R0!A%1!!11A%Z1b6#b6#k<)k<)b8#b8#b8#Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!b8#b8#b8#k<)k<)b6#b6#Z1A%11!!!1A%R,Z1b6#b6#b8#b8#b8#Z4Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4!Z4b8#b8#b8#b6#b6#Z1R,A%1!!#
168 | 1A%A%R0!R0!Z4!Z4!Z4!Z4!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z0!Z4!Z4!Z4!Z4!R0!R0!A%A%1#
169 | #
170 | #
171 | 11A%A%I*I*I*I*I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I(I*I*I*I*A%A%11#
172 | #
173 | !1119!9!9!9!9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9!9!9!9!111! !!!!))))))))))))))))))))))))))))))))))))))))))))))))!!!!
--------------------------------------------------------------------------------
/Media/Map/GoldGreenDot.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cloudbells/FieldGuide/fc16cb91683fcd1a6ec6d6005cce459660b7f1c4/Media/Map/GoldGreenDot.tga
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Field Guide
2 | An addon for World of Warcraft: Classic.
3 |
4 | Best used with [TomTom](https://www.curseforge.com/wow/addons/tomtom).
5 |
6 | **If you notice any inaccuracies or bugs please let me know!**
7 |
8 | `/fg` and `/fieldguide` will open the window.
9 |
10 | `/fg minimap` and `/fieldguide minimap` will toggle the minimap button on or off.
11 |
12 | - Use shift + scroll to scroll horizontally.
13 | - Left click on a spell to pin the nearest trainer on the map and minimap.
14 | - Right click to mark spells as unwanted.
15 | - Shift-right click a spell to mark all ranks of that spell as unwanted.
16 | - Drag any spell (even ones not learned yet) from the addon onto an action bar.
17 |
18 | 
19 |
20 | ## Features
21 | - Shows you which spells each class learns every level to plan when you need to go back to town (includes Warlock demon spells and Hunter pet skills).
22 | - Shows you which classes can learn which weapon skills (staves, one-handed swords and so on).
23 | - Tells you how much each spell/weapon skill costs to train so you know if you can afford it or not (includes PvP rank and reputation modifiers).
24 | - You can filter out known spells and/or talents.
25 | - You can mark unwanted spells by right clicking on them. Shift-right clicking on a spell will mark all the ranks of that spell.
26 | - You can drag a spell from the addon onto an action bar.
27 | - Clicking on a spell will direct you to the closest class trainer *not taking into account any flight paths/boats etc.* by making a pin on your map/minimap. If TomTom is installed, the addon will show the Crazy Arrow for you as well.
28 | - Similarly, clicking on any weapon skill will show the closest trainer for that skill *not taking into account any flight paths/boats etc.* (also lists where all trainers are when hovering over each skill).
29 |
30 | ## Features for after launch (a while after launch)
31 | - Spells that are learned through quests are currently just listed normally with a 0c cost. The plan is to direct players to/through these quests somehow.
32 | - Professions – when are Silk Bandages learned? When can Gold be smelt?
33 |
34 | ## Bugs
35 | - Some spells and ranks might be wrong, as I've gone off private server and Classic Wowhead (please get an API) data, both of which currently aren't very accurate. For example, on a certain private server (rhymes with Blight's Rope), Shadowburn rank 6 cost 2g 20s while it should have cost 11s only (baseline).
36 |
--------------------------------------------------------------------------------
/Util.lua:
--------------------------------------------------------------------------------
1 | local _, FieldGuide = ...
2 |
3 | local GetNumSkillLines, GetSkillLineInfo = GetNumSkillLines, GetSkillLineInfo
4 |
5 | FieldGuide.factions = {
6 | ["darnassus"] = 69,
7 | ["darkspear_trolls"] = 530,
8 | ["stormwind"] = 72,
9 | ["ironforge"] = 47,
10 | ["gnomeregan_exiles"] = 54,
11 | ["orgrimmar"] = 76,
12 | ["thunder_bluff"] = 81,
13 | ["undercity"] = 68,
14 | ["cenarion_circle"] = 609,
15 | ["booty_bay"] = 21,
16 | ["theramore"] = 108
17 | }
18 |
19 | FieldGuide.maps = {
20 | ["stormwind"] = 1453,
21 | ["ironforge"] = 1455,
22 | ["darnassus"] = 1457,
23 | ["orgrimmar"] = 1454,
24 | ["thunder_bluff"] = 1456,
25 | ["undercity"] = 1458,
26 | ["elwynn_forest"] = 1429,
27 | ["dun_morogh"] = 1426,
28 | ["teldrassil"] = 1438,
29 | ["tirisfal_glades"] = 1420,
30 | ["durotar"] = 1411,
31 | ["swamp_of_sorrows"] = 1435,
32 | ["felwood"] = 1448,
33 | ["moonglade"] = 1450,
34 | ["mulgore"] = 1412,
35 | ["feralas"] = 1444,
36 | ["stranglethorn_vale"] = 1434,
37 | ["stonetalon_mountains"] = 1442,
38 | ["ashenvale"] = 1440,
39 | ["loch_modan"] = 1432,
40 | ["dustwallow_marsh"] = 1445
41 | }
42 |
43 | local continents = {
44 | [1453] = 0, -- Eastern Kingdoms.
45 | [1455] = 0,
46 | [1457] = 1, -- Kalimdor.
47 | [1454] = 1,
48 | [1456] = 1,
49 | [1458] = 0,
50 | [1429] = 0,
51 | [1426] = 0,
52 | [1438] = 1,
53 | [1420] = 0,
54 | [1411] = 1,
55 | [1435] = 0,
56 | [1448] = 1,
57 | [1450] = 1,
58 | [1412] = 1,
59 | [1444] = 1,
60 | [1434] = 0,
61 | [1442] = 1,
62 | [1440] = 1,
63 | [1432] = 0,
64 | [1445] = 1
65 | }
66 |
67 | FieldGuide.pinPool = {}
68 |
69 | function FieldGuide:getPin()
70 | for _, pin in pairs(FieldGuide.pinPool) do
71 | if not pin.used then
72 | pin.used = true
73 | return pin
74 | end
75 | end
76 | FieldGuide.pinPool[#FieldGuide.pinPool + 1] = CreateFrame("Button", nil, nil, "FieldGuidePinTemplate")
77 | local pin = FieldGuide.pinPool[#FieldGuide.pinPool]
78 | pin.used = true
79 | return pin
80 | end
81 |
82 | -- Copies the given table and returns the copy. If no table is given, this returns nil.
83 | function FieldGuide.copy(original)
84 | local copy = {}
85 | if type(original) == "table" then
86 | for k, v in pairs(original) do
87 | copy[k] = v
88 | end
89 | else
90 | return nil
91 | end
92 | return copy
93 | end
94 |
95 | function FieldGuide.getContinent(map)
96 | return continents[map]
97 | end
98 |
99 | function FieldGuide.isWeaponKnown(name)
100 | for i = 1, GetNumSkillLines() do
101 | if name == GetSkillLineInfo(i) then
102 | return true
103 | end
104 | end
105 | return false
106 | end
107 |
--------------------------------------------------------------------------------