vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | |
2 | -- Add the module to the tree |
||
3 | local mod = klhtm |
||
4 | local me = {} |
||
5 | mod.data = me |
||
6 | |||
7 | --[[ |
||
8 | Data.lua |
||
9 | |||
10 | A list of constants, and a few helper methods. Raw properties of threat, talents, sets. |
||
11 | |||
12 | ]]-- |
||
13 | |||
14 | |||
15 | --[[ |
||
16 | Special onload() method called by Core. |
||
17 | ]] |
||
18 | me.onload = function() |
||
19 | |||
20 | me.infermissingspellranks() |
||
21 | |||
22 | end |
||
23 | |||
24 | --[[ |
||
25 | me.infermissingspellranks() |
||
26 | For some abilities, we don't know the threat values for all ranks. For a missing rank, we just assume the threat |
||
27 | value is <maxrank threat> * <rank> / <max rank>, where <maxrank> is the highest rank for which values are known, |
||
28 | and <rank> is the currently unknown rank. |
||
29 | ]] |
||
30 | me.infermissingspellranks = function() |
||
31 | |||
32 | local dataset, maxlevel, x, newvalues, maxlevelset |
||
33 | |||
34 | for _, dataset in me.spells do |
||
35 | |||
36 | -- only do this for class abilities without multipliers |
||
37 | if (dataset.class ~= "item") and (dataset.multiplier == nil) then |
||
38 | |||
39 | -- find the maximum rank that is known |
||
40 | for x = 20, 1, -1 do |
||
41 | maxlevel = x |
||
42 | if dataset[tostring(x)] ~= nil then |
||
43 | break |
||
44 | end |
||
45 | end |
||
46 | |||
47 | -- look for missing ranks below the maximum |
||
48 | maxlevelset = dataset[tostring(maxlevel)] |
||
49 | for x = 1, maxlevel -1 do |
||
50 | |||
51 | if dataset[tostring(x)] == nil then |
||
52 | newvalues = { } |
||
53 | newvalues.threat = math.floor(maxlevelset.threat * x / maxlevel) |
||
54 | |||
55 | -- add nextattack if it exists |
||
56 | if maxlevelset.nextattack then |
||
57 | newvalues.nextattack = math.floor(maxlevelset.nextattack * x / maxlevel) |
||
58 | end |
||
59 | |||
60 | dataset[tostring(x)] = newvalues |
||
61 | end |
||
62 | end |
||
63 | end |
||
64 | end |
||
65 | end |
||
66 | |||
67 | --[[ |
||
68 | This is basically a list of all known abilities that do threat stuff. |
||
69 | The key of each item in the list, e.g. "heroicstrike", matches the localisation key. The localised name of the spell |
||
70 | is mod.string.get("spell", <key>), e.g. mod.string.get("spell", "heroicstrike"). |
||
71 | Each spell has a <class> property, whose value is lower case, locale independent. Also it has the value "item" for |
||
72 | spells from weapons such as thunderfury or black amnesty. |
||
73 | <rage> is an optional parameter for warriors and druids, and assumed to be constant. |
||
74 | <multiplier> says that each point of damage from the spell causes x threat, where x is the value of multipler. When this |
||
75 | property is present, any <threat> value are ignored. i.e. it is assumed that a spell either multiplies the damage to get |
||
76 | threat, or adds a fixed amount, and not both. |
||
77 | For abilities with multiple ranks, add a key-value pair, where the key is the rank represented as a STRING, and the value |
||
78 | is a table with the properties of that rank. So in the table you might have a <threat> property, and a <nextattack> property. |
||
79 | ]] |
||
80 | me.spells = |
||
81 | { |
||
82 | -- only ranks 8 (default for 60) and 9 (AQ book) are known |
||
83 | ["heroicstrike"] = |
||
84 | { |
||
85 | class = "warrior", |
||
86 | rage = 15, |
||
87 | ["8"] = |
||
88 | { |
||
89 | threat = 145, |
||
90 | nextattack = 138, |
||
91 | }, |
||
92 | ["9"] = |
||
93 | { |
||
94 | ["threat"] = 173, |
||
95 | ["nextattack"] = 157, |
||
96 | } |
||
97 | }, |
||
98 | ["maul"] = |
||
99 | { |
||
100 | class = "druid", |
||
101 | rage = 15, |
||
102 | multiplier = 1.75, |
||
103 | ["7"] = { nextattack = 128 }, |
||
104 | ["6"] = { nextattack = 101 }, |
||
105 | ["5"] = { nextattack = 71 }, |
||
106 | ["4"] = { nextattack = 49 }, |
||
107 | ["3"] = { nextattack = 37 }, |
||
108 | ["2"] = { nextattack = 27 }, |
||
109 | ["1"] = { nextattack = 18 }, |
||
110 | }, |
||
111 | ["swipe"] = |
||
112 | { |
||
113 | class = "druid", |
||
114 | rage = 20, |
||
115 | multiplier = 1.75, |
||
116 | }, |
||
117 | ["shieldslam"] = |
||
118 | { |
||
119 | class = "warrior", |
||
120 | rage = 20, |
||
121 | ["4"] = { threat = 250 } |
||
122 | }, |
||
123 | ["revenge"] = |
||
124 | { |
||
125 | class = "warrior", |
||
126 | rage = 5, |
||
127 | ["5"] = { threat = 315 }, |
||
128 | ["6"] = { threat = 355 }, |
||
129 | }, |
||
130 | ["shieldbash"] = |
||
131 | { |
||
132 | class = "warrior", |
||
133 | rage = 10, |
||
134 | ["3"] = { threat = 180 }, |
||
135 | }, |
||
136 | ["sunder"] = |
||
137 | { |
||
138 | class = "warrior", |
||
139 | rage = 15, |
||
140 | ["5"] = { threat = 260 }, |
||
141 | }, |
||
142 | ["cleave"] = |
||
143 | { |
||
144 | class = "warrior", |
||
145 | rage = 20, |
||
146 | ["5"] = { threat = 100 }, |
||
147 | }, |
||
148 | ["feint"] = |
||
149 | { |
||
150 | class = "rogue", |
||
151 | ["5"] = { threat = -800 }, |
||
152 | ["4"] = { threat = -600 }, |
||
153 | ["3"] = { threat = -390 }, |
||
154 | ["2"] = { threat = -240 }, |
||
155 | ["1"] = { threat = -150 }, |
||
156 | }, |
||
157 | ["cower"] = |
||
158 | { |
||
159 | class = "druid", |
||
160 | rage = 0, |
||
161 | ["3"] = { threat = -600 }, |
||
162 | ["2"] = { threat = -390 }, |
||
163 | ["1"] = { threat = -240 }, |
||
164 | }, |
||
165 | ["searingpain"] = |
||
166 | { |
||
167 | class = "warlock", |
||
168 | multiplier = 2.0, |
||
169 | }, |
||
170 | ["earthshock"] = |
||
171 | { |
||
172 | class = "shaman", |
||
173 | multiplier = 2.0, |
||
174 | }, |
||
175 | ["mindblast"] = |
||
176 | { |
||
177 | class = "priest", |
||
178 | multiplier = 2.0, |
||
179 | }, |
||
180 | ["holyshield"] = |
||
181 | { |
||
182 | class = "paladin", |
||
183 | multiplier = 1.2, |
||
184 | }, |
||
185 | ["distractingshot"] = |
||
186 | { |
||
187 | class = "hunter", |
||
188 | ["1"] = { threat = 110 }, |
||
189 | ["2"] = { threat = 160 }, |
||
190 | ["3"] = { threat = 250 }, |
||
191 | ["4"] = { threat = 350 }, |
||
192 | ["5"] = { threat = 465 }, |
||
193 | ["6"] = { threat = 600 }, |
||
194 | }, |
||
195 | ["fade"] = |
||
196 | { |
||
197 | class = "priest", |
||
198 | ["1"] = { threat = 55 }, |
||
199 | ["2"] = { threat = 155 }, |
||
200 | ["3"] = { threat = 285 }, |
||
201 | ["4"] = { threat = 440 }, |
||
202 | ["5"] = { threat = 620 }, |
||
203 | ["6"] = { threat = 820 }, |
||
204 | }, |
||
205 | ["thunderfury"] = |
||
206 | { |
||
207 | class = "item", |
||
208 | threat = 241, |
||
209 | }, |
||
210 | ["graceofearth"] = |
||
211 | { |
||
212 | class = "item", |
||
213 | threat = -650, |
||
214 | }, |
||
215 | ["blackamnesty"] = |
||
216 | { |
||
217 | class = "item", |
||
218 | threat = -540, |
||
219 | }, |
||
220 | ["whitedamage"] = |
||
221 | { |
||
222 | class = "item", |
||
223 | threat = 0, |
||
224 | }, |
||
225 | } |
||
226 | |||
227 | -- These are the DPS modifiers for ranks of rockbiter. Whenever a hit lands with a rockbiter weapon, the added threat |
||
228 | -- equals the speed of the weapon times the rockbiter value, e.g. 72 dps for max rank. |
||
229 | me.rockbiter = |
||
230 | { |
||
231 | [1] = 6, -- 1 |
||
232 | [2] = 10, -- 8 |
||
233 | [3] = 16, -- 16 |
||
234 | [4] = 27, -- 24 |
||
235 | [5] = 41, -- 34 |
||
236 | [6] = 55, -- 44 |
||
237 | [7] = 72, -- 54 |
||
238 | } |
||
239 | |||
240 | -- A bunch of firm constants. |
||
241 | me.threatconstants = |
||
242 | { |
||
243 | ["healing"] = 0.5, |
||
244 | ["meleeaggrogain"] = 1.1, |
||
245 | ["rangeaggrogain"] = 1.3, |
||
246 | ["ragegain"] = 5.0, |
||
247 | ["energygain"] = 5.0, |
||
248 | ["managain"] = 0.5, |
||
249 | } |
||
250 | |||
251 | --[[ |
||
252 | mod.data.isbuffpresent(texture) |
||
253 | Looks in your buff list for an icon matching the supplied texture. |
||
254 | <texture> is the path of the texture, e.g. "Interface\\Icons\\Ability_Warrior_Sunder" |
||
255 | Returns: true if the buff is present, false otherwise |
||
256 | ]] |
||
257 | me.isbuffpresent = function(texture) |
||
258 | |||
259 | local x |
||
260 | local bufftexture |
||
261 | |||
262 | for x = 1, 16 do |
||
263 | bufftexture = UnitBuff("player", x) |
||
264 | |||
265 | if bufftexture == nil then |
||
266 | break |
||
267 | |||
268 | elseif bufftexture == texture then |
||
269 | return true |
||
270 | end |
||
271 | end |
||
272 | |||
273 | return false |
||
274 | end |
||
275 | |||
276 | -------------------------------------------------------------------------- |
||
277 | |||
278 | ------------------------------ |
||
279 | -- Spell Sets -- |
||
280 | ------------------------------ |
||
281 | |||
282 | --[[ |
||
283 | Certain items and abilities only affect particular schools of spells. For these specific sets, we keep |
||
284 | a list of all the possible spells, and provide a method to query a spell as from a school. |
||
285 | ]] |
||
286 | me.spellsets = |
||
287 | { |
||
288 | ["Warlock Destruction"] = |
||
289 | { "shadowbolt", "immolate", "conflagrate", "searingpain", "rainoffire", "soulfire", "shadowburn", "hellfire" }, |
||
290 | } |
||
291 | |||
292 | --[[ |
||
293 | mod.data.spellmatchesset(setname, spellname) |
||
294 | Returns: true if the spell is in the set, false otherwise. |
||
295 | <setname> is a key to me.spellsets above, e.g. "Priest Shadow Spells". |
||
296 | <spellname> is the name of a spell. It is localised. |
||
297 | ]] |
||
298 | me.spellmatchesset = function(setname, spellid) |
||
299 | |||
300 | local x = 0 |
||
301 | local spellset = me.spellsets[setname] |
||
302 | local spell |
||
303 | |||
304 | while true do |
||
305 | x = x + 1 |
||
306 | spell = spellset[x] |
||
307 | |||
308 | if spell == nil then |
||
309 | return false |
||
310 | |||
311 | elseif spell == spellid then |
||
312 | return true |
||
313 | end |
||
314 | end |
||
315 | |||
316 | end |
||
317 | |||
318 | |||
319 | -------------------------------------------------------------------------- |
||
320 | |||
321 | ------------------------------ |
||
322 | -- Talent Points -- |
||
323 | ------------------------------ |
||
324 | |||
325 | -- Values are {Page, Talent, Class} |
||
326 | me.talentinfo = |
||
327 | { |
||
328 | sunder = {3, 10, "warrior"}, |
||
329 | heroicstrike = {1, 1, "warrior"}, |
||
330 | defiance = {3, 9, "warrior"}, |
||
331 | impale = {1, 11, "warrior"}, |
||
332 | silentresolve = {1, 3, "priest"}, |
||
333 | shadowaffinity = {3, 3, "priest"}, |
||
334 | druidsubtlety = {3, 8, "druid"}, |
||
335 | feralinstinct = {2, 3, "druid"}, |
||
336 | ferocity = {2, 1, "druid"}, |
||
337 | tranquility = {3, 13, "druid"}, |
||
338 | savagefury = {2, 13,"druid"}, |
||
339 | masterdemonologist = {2, 15, "warlock"}, |
||
340 | arcanesubtlety = {1, 1, "mage"}, |
||
341 | frostchanneling = {3, 12, "mage"}, |
||
342 | burningsoul = {2, 9, "mage"}, |
||
343 | righteousfury = {2, 7, "paladin"}, |
||
344 | healinggrace = {3, 9, "shaman"}, |
||
345 | } |
||
346 | |||
347 | --[[ |
||
348 | me.gettalentrank(talent) |
||
349 | Returns: how many points you have invested in the specified talent. |
||
350 | <talent> is a value from the me.talentinfo array. |
||
351 | ]] |
||
352 | me.gettalentrank = function(talent) |
||
353 | |||
354 | local info = me.talentinfo[talent] |
||
355 | local rank |
||
356 | _, _, _, _, rank = GetTalentInfo(info[1], info[2]) |
||
357 | |||
358 | return rank |
||
359 | end |
||
360 | |||
361 | -- This is a pretty simple function to print out the talents you havee that the mod is checking for |
||
362 | me.testtalents = function() |
||
363 | |||
364 | local key, value, rank |
||
365 | local numtalents = 0 |
||
366 | |||
367 | for key, value in me.talentinfo do |
||
368 | |||
369 | if value[3] == mod.my.class then |
||
370 | rank = me.gettalentrank(key) |
||
371 | numtalents = numtalents + 1 |
||
372 | |||
373 | mod.out.print(string.format(mod.string.get("print", "data", "talentpoint"), rank, mod.string.get("talent", key))) |
||
374 | end |
||
375 | end |
||
376 | |||
377 | mod.out.print(string.format(mod.string.get("print", "data", "talent"), numtalents, UnitClass("player"))) |
||
378 | end |
||
379 | |||
380 | |||
381 | -------------------------------------------------------------------------- |
||
382 | |||
383 | ------------------------------------------- |
||
384 | -- Checking for Set Pieces -- |
||
385 | ------------------------------------------- |
||
386 | |||
387 | -- This will print a list of all the (significant) set pieces you are wearing. |
||
388 | me.testitemsets = function() |
||
389 | |||
390 | local setname |
||
391 | local output |
||
392 | local pieces |
||
393 | |||
394 | for setname in me.itemsets do |
||
395 | output = mod.string.get("sets", setname) .. ": {" |
||
396 | _, pieces = me.getsetpieces(setname, "non-nil") |
||
397 | output = output .. pieces .. "}" |
||
398 | mod.out.print(output) |
||
399 | end |
||
400 | |||
401 | end |
||
402 | |||
403 | -- the key is the description, the value is the item slot index, for GetInventoryItemLink |
||
404 | me.itemslots = |
||
405 | { |
||
406 | head = 1, |
||
407 | legs = 7, |
||
408 | shoulder = 3, |
||
409 | feet = 8, |
||
410 | waist = 6, |
||
411 | wrist = 9, |
||
412 | chest = 5, |
||
413 | hands = 10, |
||
414 | } |
||
415 | |||
416 | -- values are item numbers. The numbers will be contained in an item link string. |
||
417 | me.itemsets = |
||
418 | { |
||
419 | might = |
||
420 | { |
||
421 | head = "16866", |
||
422 | legs = "16867", |
||
423 | shoulder = "16868", |
||
424 | feet = "16862", |
||
425 | waist = "16864", |
||
426 | wrist = "16861", |
||
427 | chest = "16865", |
||
428 | hands = "16863", |
||
429 | }, |
||
430 | bloodfang = |
||
431 | { |
||
432 | head = "16908", |
||
433 | legs = "16909", |
||
434 | shoulder = "16832", |
||
435 | feet = "16906", |
||
436 | waist = "16910", |
||
437 | wrist = "16911", |
||
438 | chest = "16905", |
||
439 | hands = "16907", |
||
440 | }, |
||
441 | arcanist = |
||
442 | { |
||
443 | head = "16795", |
||
444 | legs = "16796", |
||
445 | shoulder = "16797", |
||
446 | feet = "16800", |
||
447 | waist = "16802", |
||
448 | wrist = "16799", |
||
449 | chest = "16798", |
||
450 | hands = "16801", |
||
451 | }, |
||
452 | netherwind = |
||
453 | { |
||
454 | head = "16914", |
||
455 | legs = "16915", |
||
456 | shoulder = "16917", |
||
457 | feet = "16912", |
||
458 | waist = "16818", |
||
459 | wrist = "16918", |
||
460 | chest = "16916", |
||
461 | hands = "16913", |
||
462 | }, |
||
463 | nemesis = |
||
464 | { |
||
465 | head = "16929", |
||
466 | legs = "16930", |
||
467 | shoulder = "16932", |
||
468 | feet = "16927", |
||
469 | waist = "16933", |
||
470 | wrist = "16934", |
||
471 | chest = "16931", |
||
472 | hands = "16928", |
||
473 | }, |
||
474 | } |
||
475 | |||
476 | --[[ |
||
477 | mod.data.getsetpieces(setname, isdebug) |
||
478 | Returns: the number of set pieces the player is currently wearing. |
||
479 | <setname> is the localised name of the set. |
||
480 | if <isdebug> is non-nil, the method will also generate and return as the second value a printout. |
||
481 | ]] |
||
482 | me.getsetpieces = function(setname, isdebug) |
||
483 | |||
484 | -- 1) Get the set list |
||
485 | local setlist = me.itemsets[setname] |
||
486 | |||
487 | if setlist == nil then |
||
488 | me.out.printtrace("assertion", string.format("The set |cffffff00%s|r does not exist in our database.", setname)) |
||
489 | return 0 |
||
490 | end |
||
491 | |||
492 | local slotname |
||
493 | local slotnumber |
||
494 | local debugout = "" |
||
495 | local itemlink |
||
496 | local numitems = 0 |
||
497 | |||
498 | for slotname, slotnumber in me.itemslots do |
||
499 | itemlink = GetInventoryItemLink("player", slotnumber) |
||
500 | |||
501 | if itemlink and string.find(itemlink, setlist[slotname]) then |
||
502 | numitems = numitems + 1 |
||
503 | |||
504 | -- if it's for debug, print out which piece it is |
||
505 | if isdebug then |
||
506 | if numitems > 1 then |
||
507 | debugout = debugout .. ", " |
||
508 | end |
||
509 | |||
510 | debugout = debugout .. slotname |
||
511 | end |
||
512 | end |
||
513 | end |
||
514 | |||
515 | return numitems, debugout |
||
516 | |||
517 | end |