├── .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 |