vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 local _, class = UnitClass("player")
2 local returndata = {}
3 local summeddata = {}
4  
5 local function findpattern(text, pattern, start)
6 if (text and pattern and (string.find(text, pattern, start))) then
7 return string.sub(text, string.find(text, pattern, start))
8 else
9 return ""
10 end
11 end
12  
13 local function round(arg1, decplaces)
14 if (decplaces == nil) then decplaces = 0 end
15 if arg1 == nil then arg1 = 0 end
16 return string.format ("%."..decplaces.."f", arg1)
17 end
18  
19 local function TheoryCraft_AddData(arg1, data, summeddata)
20 if data == nil then return end
21 summeddata["tmpincrease"] = summeddata["tmpincrease"] + (data[arg1.."modifier"] or 0)
22 summeddata["tmpincreaseupfront"] = summeddata["tmpincreaseupfront"] + (data[arg1.."UpFrontmodifier"] or 0)
23 if summeddata["baseincrease"] ~= 0 then
24 summeddata["baseincrease"] = summeddata["baseincrease"] * ((data[arg1.."baseincrease"] or 0)+1)
25 else
26 summeddata["baseincrease"] = summeddata["baseincrease"] + (data[arg1.."baseincrease"] or 0)
27 end
28 if summeddata["baseincreaseupfront"] ~= 0 then
29 summeddata["baseincreaseupfront"] = summeddata["baseincreaseupfront"] * ((data[arg1.."UpFrontbaseincrease"] or 0)+1)
30 else
31 summeddata["baseincreaseupfront"] = summeddata["baseincreaseupfront"] + (data[arg1.."UpFrontbaseincrease"] or 0)
32 end
33 summeddata["talentmod"] = summeddata["talentmod"] + (data[arg1.."talentmod"] or 0)
34 summeddata["talentmodupfront"] = summeddata["talentmodupfront"] + (data[arg1.."UpFronttalentmod"] or 0)
35 if (summeddata["doshatter"] ~= 0) then
36 summeddata["critchance"] = summeddata["critchance"] + (data[arg1.."shatter"] or 0)
37 end
38 summeddata["illum"] = summeddata["illum"] + (data[arg1.."illum"] or 0)
39 summeddata["plusdam"] = summeddata["plusdam"] + (data[arg1] or 0)
40 summeddata["manacostmod"] = summeddata["manacostmod"] + (data[arg1.."manacost"] or 0)
41 summeddata["critchance"] = summeddata["critchance"] + (data[arg1.."critchance"] or 0)
42 summeddata["critbonus"] = summeddata["critbonus"] + (data[arg1.."critbonus"] or 0)
43 summeddata["ignitemodifier"] = summeddata["ignitemodifier"] + (data[arg1.."ignitemodifier"] or 0)
44 summeddata["sepignite"] = summeddata["sepignite"] + (data[arg1.."sepignite"] or 0)
45 summeddata["hitbonus"] = summeddata["hitbonus"] - (data[arg1.."hitchance"] or 0)
46 summeddata["casttime"] = summeddata["casttime"] + (data[arg1.."casttime"] or 0)
47 summeddata["regencasttime"] = summeddata["regencasttime"] + (data[arg1.."casttime"] or 0)
48 summeddata["penetration"] = summeddata["penetration"] + (data[arg1.."penetration"] or 0)
49 summeddata["grace"] = summeddata["grace"] + (data[arg1.."grace"] or 0)
50 summeddata["threat"] = summeddata["threat"] + (data[arg1.."threat"] or 0)
51 if data[arg1.."Netherwind"] == 1 then
52 summeddata["netherwind"] = 1
53 end
54 end
55  
56 local function TheoryCraft_DoSchool(arg1, summeddata)
57 if TheoryCraft_Data.Testing then
58 TheoryCraft_AddData(arg1, TheoryCraft_Data.TalentsTest, summeddata)
59 else
60 TheoryCraft_AddData(arg1, TheoryCraft_Data.Talents, summeddata)
61 end
62 TheoryCraft_AddData(arg1, TheoryCraft_Data.BaseData, summeddata)
63 TheoryCraft_AddData(arg1, TheoryCraft_Data.Stats, summeddata)
64 TheoryCraft_AddData(arg1, TheoryCraft_Data.PlayerBuffs, summeddata)
65 TheoryCraft_AddData(arg1, TheoryCraft_Data.TargetBuffs, summeddata)
66 TheoryCraft_AddData(arg1, TheoryCraft_Data.EquipEffects, summeddata)
67 TheoryCraft_AddData(arg1, TheoryCraft_Data.Target, summeddata)
68 end
69  
70 local function SummateData(name, schools)
71 TheoryCraft_DeleteTable(summeddata)
72 summeddata["doshatter"] = (TheoryCraft_Data.TargetBuffs["doshatter"] or 0)
73 summeddata["tmpincrease"] = 0
74 summeddata["tmpincreaseupfront"] = 0
75 summeddata["baseincrease"] = 0
76 summeddata["baseincreaseupfront"] = 0
77 summeddata["talentmod"] = 0
78 summeddata["talentmodupfront"] = 0
79 summeddata["critchance"] = (TheoryCraft_Data.Stats["critchance"] or 0)
80 summeddata["illum"] = 0
81 summeddata["plusdam"] = 0
82 summeddata["manacostmod"] = 1
83 summeddata["critbonus"] = 0
84 summeddata["ignitemodifier"] = 0
85 summeddata["sepignite"] = 0
86 summeddata["hitbonus"] = 0
87 summeddata["casttime"] = 0
88 summeddata["regencasttime"] = 0
89 summeddata["penetration"] = 0
90 summeddata["grace"] = 0
91 summeddata["netherwind"] = 0
92 summeddata["threat"] = 0
93 for k, v in pairs (schools) do
94 TheoryCraft_DoSchool(v, summeddata)
95 end
96 TheoryCraft_DoSchool(name, summeddata)
97 end
98  
99 local function getcooldown(frame)
100 index = 1
101 local rtext = getglobal(frame:GetName().."TextRight"..index):GetText()
102 local cooldown = 1.5
103 while (rtext) do
104 if (getglobal(frame:GetName().."TextRight"..index):IsVisible()) then
105 if (strfind(rtext, "%d+.%d+"..TheoryCraft_Locale.Cooldown)) then
106 cooldown = findpattern(rtext, "%d+.%d+");
107 elseif (strfind(rtext, "%d+"..TheoryCraft_Locale.Cooldown)) then
108 cooldown = findpattern(rtext, "%d+");
109 end
110 end
111 index = index + 1;
112 rtext = getglobal(frame:GetName().."TextRight"..index):GetText()
113 end
114 return cooldown
115 end
116  
117 local function getlifetap(returndata)
118 local i2 = 1
119 local spellname = 1
120 local spellrank = 1
121 local quit = 0
122 local found = 0
123 while (spellname) do
124 spellname, spellrank = GetSpellName(i2,BOOKTYPE_SPELL)
125 spellrank = tonumber(findpattern(spellrank, "%d+"))
126 if (spellname == TheoryCraft_Locale.lifetap) then
127 found = 1
128 elseif (found == 1) then
129 TCTooltip:SetOwner(UIParent,"ANCHOR_NONE")
130 TCTooltip:SetSpell(i2-1,BOOKTYPE_SPELL)
131 if (TCTooltip:NumLines() > 0) then
132 local description = getglobal("TCTooltipTextLeft"..TCTooltip:NumLines()):GetText()
133 returndata["lifetapHealth"] = findpattern(description, "%d+ health")
134 returndata["lifetapMana"] = findpattern(description, "%d+ mana")
135 if returndata["lifetapHealth"] then
136 returndata["lifetapHealth"] = tonumber(findpattern(returndata["lifetapHealth"], "%d+"))
137 end
138 if returndata["lifetapMana"] then
139 returndata["lifetapMana"] = tonumber(findpattern(returndata["lifetapMana"], "%d+"))
140 end
141 end
142 return
143 end
144 i2 = i2 + 1
145 end
146 end
147  
148 function TheoryCraft_GetStat(statname)
149 if TheoryCraft_Data.testing then
150 return (TheoryCraft_Data.BaseData[statname] or 0)+
151 (TheoryCraft_Data.TalentsTest[statname] or 0)+
152 (TheoryCraft_Data.Stats[statname] or 0)+
153 (TheoryCraft_Data.PlayerBuffs[statname] or 0)+
154 (TheoryCraft_Data.TargetBuffs[statname] or 0)+
155 (TheoryCraft_Data.EquipEffects[statname] or 0)+
156 (TheoryCraft_Data.Target[statname] or 0)
157 else
158 return (TheoryCraft_Data.BaseData[statname] or 0)+
159 (TheoryCraft_Data.Talents[statname] or 0)+
160 (TheoryCraft_Data.Stats[statname] or 0)+
161 (TheoryCraft_Data.PlayerBuffs[statname] or 0)+
162 (TheoryCraft_Data.TargetBuffs[statname] or 0)+
163 (TheoryCraft_Data.EquipEffects[statname] or 0)+
164 (TheoryCraft_Data.Target[statname] or 0)
165 end
166 end
167  
168 local function agipercrit()
169 if TheoryCraft_agipercrit then
170 return TheoryCraft_agipercrit
171 else
172 return TheoryCraft_CritChance[class][1]
173 end
174 end
175  
176 function TheoryCraft_intpercrit()
177 local critdivider
178 local agipercrit = agipercrit()
179 if agipercrit == TheoryCraft_CritChance[class][1] then
180 critdivider = UnitLevel("player")/60*TheoryCraft_CritChance[class][2]
181 if (critdivider < 5) then
182 critdivider = 5
183 end
184 else
185 critdivider = agipercrit/TheoryCraft_CritChance[class][1]*TheoryCraft_CritChance[class][2]
186 end
187 return critdivider
188 end
189  
190 --- Returns the cast time from the spell tooltip ---
191  
192 local function getcasttime(frame)
193 index = 1;
194 local ltext = getglobal(frame:GetName().."TextLeft"..index):GetText()
195 local castTime = 0
196 while (ltext) do
197 ltext = string.gsub(ltext, ",", ".")
198 if (strfind(ltext, "%d+.%d+"..TheoryCraft_Locale.SecCast)) then
199 castTime = findpattern(findpattern(ltext, "%d+.%d+"..TheoryCraft_Locale.SecCast), "%d+.%d+")
200 elseif (strfind(ltext, "%d+"..TheoryCraft_Locale.SecCast)) then
201 castTime = findpattern(findpattern(ltext, "%d+"..TheoryCraft_Locale.SecCast), "%d+")
202 end
203 index = index + 1
204 ltext = getglobal(frame:GetName().."TextLeft"..index):GetText()
205 end
206 castTime = tonumber(castTime)
207 return castTime
208 end
209  
210 --- Returns the dot duration from the spell tooltip ---
211  
212 local function TheoryCraft_getDotDuration(description)
213 local i = 1
214 local _, found
215 while TheoryCraft_DotDurations[i] do
216 if (strfind(description, TheoryCraft_DotDurations[i].text)) then
217 if TheoryCraft_DotDurations[i].amount == "n" then
218 _, _, found = strfind(description, TheoryCraft_DotDurations[i].text)
219 return found
220 else
221 return TheoryCraft_DotDurations[i].amount
222 end
223 end
224 i = i + 1
225 end
226 return 1
227 end
228  
229 local function getmanacost(frame)
230 index = 1
231 local ltext = getglobal(frame:GetName().."TextLeft"..index):GetText()
232 local manaCost = 0
233 while (ltext) do
234 if (strfind(ltext, TheoryCraft_Locale.Mana)) then
235 manaCost = findpattern(ltext, "%d+")
236 end
237 index = index + 1;
238 ltext = getglobal(frame:GetName().."TextLeft"..index):GetText()
239 end
240 manaCost = tonumber(manaCost)
241 if manaCost then
242 return manaCost
243 else
244 return 0
245 end
246 end
247  
248 local function TheoryCraft_GetRangedSpeed()
249 TheoryCraftTooltip:SetOwner(UIParent,"ANCHOR_NONE")
250 TheoryCraftTooltip:SetInventoryItem ("player", GetInventorySlotInfo("RangedSlot"))
251 local index = 1
252 ltext = getglobal(TheoryCraftTooltip:GetName().."TextLeft"..index)
253 rtext = getglobal(TheoryCraftTooltip:GetName().."TextRight"..index)
254 if ltext then
255 ltext = ltext:GetText()
256 end
257 if rtext then
258 if not (getglobal(TheoryCraftTooltip:GetName().."TextRight"..index):IsVisible()) then
259 rtext = nil
260 else
261 rtext = rtext:GetText()
262 end
263 end
264 while (ltext ~= nil) do
265 if (rtext) then
266 for k, v in pairs(TheoryCraft_EquipEveryRight) do
267 if (v.slot == nil) or (v.slot == "Ranged") then
268 _, start, found = strfind(rtext, v.text)
269 if found then
270 if v.amount then
271 TheoryCraftTooltip:ClearLines()
272 return v.amount
273 else
274 TheoryCraftTooltip:ClearLines()
275 return found
276 end
277 end
278 end
279 end
280 end
281 index = index + 1;
282 ltext = getglobal(TheoryCraftTooltip:GetName().."TextLeft"..index)
283 rtext = getglobal(TheoryCraftTooltip:GetName().."TextRight"..index)
284 if ltext then
285 ltext = ltext:GetText()
286 end
287 if rtext then
288 if not (getglobal(TheoryCraftTooltip:GetName().."TextRight"..index):IsVisible()) then
289 rtext = nil
290 else
291 rtext = rtext:GetText()
292 end
293 end
294 end
295 TheoryCraftTooltip:ClearLines()
296 return 2.8
297 end
298  
299 local function GetCritChance(critreport)
300 local critChance, iCritInfo, critNum
301 local remove = 0
302 local id = 1
303 local attackSpell = GetSpellName(id,BOOKTYPE_SPELL)
304 if (attackSpell ~= TheoryCraft_Locale.Attack) then
305 name, texture, offset, numSpells = GetSpellTabInfo(1)
306 for i=1, numSpells do
307 if (GetSpellName(i,BOOKTYPE_SPELL) == TheoryCraft_Locale.Attack) then
308 id = i
309 end
310 end
311 end
312 if GetSpellName(id,BOOKTYPE_SPELL) ~= TheoryCraft_Locale.Attack then
313 return 0
314 end
315 TheoryCraftTooltip:SetOwner(UIParent,"ANCHOR_NONE")
316 TheoryCraftTooltip:SetSpell(id, BOOKTYPE_SPELL)
317 local spellName = TheoryCraftTooltipTextLeft2:GetText()
318 if not spellName then return 0 end
319 iCritInfo = string.find(spellName, "%s")
320 critNum = string.sub(spellName,0,(iCritInfo -2))
321 critChance = string.gsub(critNum, ",", ".")
322 critChance = tonumber(critChance)
323 if critreport == nil then critreport = 0 end
324 if (critChance) and (critChance ~= critreport) then
325 local doweaponskill = true
326 if class == "DRUID" then
327 local _, _, active = GetShapeshiftFormInfo(1)
328 if active then doweaponskill = nil end
329 local _, _, active = GetShapeshiftFormInfo(3)
330 if active then doweaponskill = nil end
331 end
332 if doweaponskill then
333 TheoryCraftTooltip:SetOwner(UIParent,"ANCHOR_NONE")
334 TheoryCraftTooltip:SetInventoryItem ("player", GetInventorySlotInfo("MainHandSlot"))
335 local i, i2 = 1
336 local ltext = getglobal(TheoryCraftTooltip:GetName().."TextLeft"..i):GetText()
337 local rtext = getglobal(TheoryCraftTooltip:GetName().."TextRight"..i):GetText()
338 local skill = TheoryCraft_WeaponSkillOther
339 local english = "Unarmed"
340 while ltext do
341 ltext = getglobal(TheoryCraftTooltip:GetName().."TextLeft"..i):GetText()
342 rtext = getglobal(TheoryCraftTooltip:GetName().."TextRight"..i):GetText()
343 if (rtext) and (getglobal(TheoryCraftTooltip:GetName().."TextRight"..i):IsVisible()) then
344 i2 = 1
345 while TheoryCraft_WeaponSkills[i2] do
346 if (((TheoryCraft_WeaponSkills[i2].ltext) and (TheoryCraft_WeaponSkills[i2].ltext == ltext)) or (TheoryCraft_WeaponSkills[i2].ltext == nil)) and (TheoryCraft_WeaponSkills[i2].text == rtext) then
347 skill = TheoryCraft_WeaponSkills[i2].skill
348 english = TheoryCraft_WeaponSkills[i2].english
349 break
350 end
351 i2 = i2 + 1
352 end
353 end
354 if skill ~= TheoryCraft_WeaponSkillOther then
355 break
356 end
357 i = i + 1
358 end
359 local i = 1
360 local skillTitle, header, isExpanded, skillRank
361 while GetSkillLineInfo(i) do
362 skillTitle, header, isExpanded, skillRank = GetSkillLineInfo(i)
363 if (skillTitle == skill) then
364 critChance = critChance + (UnitLevel("player")*5 - skillRank)*0.04
365 break
366 end
367 i = i + 1
368 end
369 -- remove weapon specs
370 critChance = critChance - TheoryCraft_GetStat(english.."specreal")
371 end
372 critChance = critChance - (TheoryCraft_GetStat("CritChangeTalents") or 0)
373 if doweaponskill == nil then
374 critChance = critChance - (TheoryCraft_Data.Talents["Formcritchancereal"] or 0)
375 remove = -1*(TheoryCraft_Data.Talents["Formcritchancereal"] or 0)
376 end
377 local critchance2 = critChance-TheoryCraft_GetStat("CritReport")
378 if doweaponskill == nil then
379 critChance = critChance + (TheoryCraft_Data.Talents["Formcritchance"] or 0)
380 end
381 if class == "WARRIOR" then
382 local _, _, active = GetShapeshiftFormInfo(3)
383 if active then
384 critchance2 = critchance2 - 3
385 remove = -3
386 end
387 end
388 if UnitLevel("player") == 60 then
389 if (class == "DRUID") then
390 if doweaponskill == nil then
391 remove = -1*(TheoryCraft_Data.Talents["Formcritchance"] or 0)
392 end
393 end
394 TheoryCraft_agipercrit = TheoryCraft_CritChance[class][1]
395 else
396 if (TheoryCraft_Data["outfit"] == nil) or (TheoryCraft_Data["outfit"] == 1) then
397 local _, agi = UnitStat("player", 2)
398 TheoryCraft_agipercrit = agi/(critchance2-TheoryCraft_CritChance[class][3])
399 end
400 end
401 return (critChance or 0), remove
402 else
403 return 0, remove
404 end
405 end
406  
407 function TheoryCraft_LoadStats(talents)
408 if talents == nil then talents = TheoryCraft_Data.Talents end
409 TheoryCraft_DeleteTable(TheoryCraft_Data.Stats)
410 local remove
411 TheoryCraft_Data.Stats["meleecritchance"], remove = GetCritChance()
412 TheoryCraft_Data.Stats["Rangedhastebonus"] = UnitRangedDamage("player")/TheoryCraft_GetRangedSpeed()
413 local outfit = (TheoryCraft_Data["outfit"] or 1)
414 if outfit == -1 then
415 outfit = 1
416 end
417  
418 local _, tmp = UnitStat("player", 1)
419 TheoryCraft_Data.Stats["strength"] = tmp
420 _, tmp = UnitStat("player", 2)
421 TheoryCraft_Data.Stats["agility"] = tmp
422 _, tmp = UnitStat("player", 3)
423 TheoryCraft_Data.Stats["stamina"] = tmp
424 _, tmp = UnitStat("player", 4)
425 TheoryCraft_Data.Stats["intellect"] = tmp
426 _, tmp = UnitStat("player", 5)
427 TheoryCraft_Data.Stats["spirit"] = tmp
428 TheoryCraft_Data.Stats["agipercrit"] = agipercrit()
429  
430 local _, catform, bearform
431 if class == "DRUID" then
432 _, _, bearform = GetShapeshiftFormInfo(1)
433 _, _, catform = GetShapeshiftFormInfo(3)
434 TheoryCraft_Data.Stats["agilityapranged"] = 2
435 TheoryCraft_Data.Stats["strengthapmelee"] = 2
436 if catform then
437 TheoryCraft_Data.Stats["agilityapmelee"] = 1
438 else
439 TheoryCraft_Data.Stats["agilityapmelee"] = 0
440 end
441 elseif (class == "WARRIOR") or (class == "PALADIN") or (class == "SHAMAN") then
442 TheoryCraft_Data.Stats["agilityapranged"] = 2
443 TheoryCraft_Data.Stats["strengthapmelee"] = 2
444 TheoryCraft_Data.Stats["agilityapmelee"] = 0
445 elseif (class == "ROGUE") or (class == "HUNTER") then
446 TheoryCraft_Data.Stats["agilityapranged"] = 2
447 TheoryCraft_Data.Stats["strengthapmelee"] = 1
448 TheoryCraft_Data.Stats["agilityapmelee"] = 1
449 else
450 TheoryCraft_Data.Stats["agilityapranged"] = 0
451 TheoryCraft_Data.Stats["strengthapmelee"] = 1
452 TheoryCraft_Data.Stats["agilityapmelee"] = 0
453 end
454  
455 local base, pos, neg = UnitAttackPower("player")
456 TheoryCraft_Data.Stats["attackpower"] = base+pos+neg-TheoryCraft_Data.Stats["strengthapmelee"]*TheoryCraft_Data.Stats["strength"]-TheoryCraft_Data.Stats["agilityapmelee"]*TheoryCraft_Data.Stats["agility"]+(talents["AttackPowerTalents"] or 0)
457 base, pos, neg = UnitRangedAttackPower("player")
458 TheoryCraft_Data.Stats["rangedattackpower"] = (TheoryCraft_Data.TargetBuffs["huntersmark"] or 0)+base+pos+neg-TheoryCraft_Data.Stats["agilityapranged"]*TheoryCraft_Data.Stats["agility"]
459  
460 TheoryCraft_Data.Stats["totalmana"] = UnitManaMax("player")/talents["manamultiplierreal"]
461 TheoryCraft_Data.Stats["totalhealth"] = UnitHealthMax("player")/talents["healthmultiplierreal"]
462  
463 TheoryCraft_Data.Stats["meleecritchance"] = TheoryCraft_Data.Stats["meleecritchance"]-TheoryCraft_Data.Stats["agility"]/TheoryCraft_Data.Stats["agipercrit"]
464 TheoryCraft_Data.Stats["totalhealth"] = TheoryCraft_Data.Stats["totalhealth"] - TheoryCraft_Data.Stats["stamina"]*10
465 TheoryCraft_Data.Stats["totalmana"] = TheoryCraft_Data.Stats["totalmana"] - TheoryCraft_Data.Stats["intellect"]*15
466  
467 TheoryCraft_Data.Stats["strength"] = TheoryCraft_Data.Stats["strength"]/talents["strmultiplierreal"]
468 TheoryCraft_Data.Stats["agility"] = TheoryCraft_Data.Stats["agility"]/talents["agimultiplierreal"]
469 TheoryCraft_Data.Stats["stamina"] = TheoryCraft_Data.Stats["stamina"]/talents["stammultiplierreal"]
470 TheoryCraft_Data.Stats["intellect"] = TheoryCraft_Data.Stats["intellect"]/talents["intmultiplierreal"]
471 TheoryCraft_Data.Stats["spirit"] = TheoryCraft_Data.Stats["spirit"]/talents["spiritmultiplierreal"]
472 TheoryCraft_Data.Stats["formattackpower"] = 0
473  
474 if (TheoryCraft_Outfits[outfit].meleecritchance) then TheoryCraft_Data.Stats["meleecritchance"] = TheoryCraft_Data.Stats["meleecritchance"]+TheoryCraft_Outfits[outfit].meleecritchance end
475 if (TheoryCraft_Outfits[outfit].rangedattackpower) then TheoryCraft_Data.Stats["rangedattackpower"] = TheoryCraft_Data.Stats["rangedattackpower"]+TheoryCraft_Outfits[outfit].rangedattackpower end
476 if (TheoryCraft_Outfits[outfit].attackpower) then TheoryCraft_Data.Stats["attackpower"] = TheoryCraft_Data.Stats["attackpower"]+TheoryCraft_Outfits[outfit].attackpower end
477 if (TheoryCraft_Outfits[outfit].formattackpower) then TheoryCraft_Data.Stats["formattackpower"] = TheoryCraft_Data.Stats["formattackpower"]+TheoryCraft_Outfits[outfit].formattackpower end
478 if (TheoryCraft_Outfits[outfit].strength) then TheoryCraft_Data.Stats["strength"] = TheoryCraft_Data.Stats["strength"]+TheoryCraft_Outfits[outfit].strength end
479 if (TheoryCraft_Outfits[outfit].agility) then TheoryCraft_Data.Stats["agility"] = TheoryCraft_Data.Stats["agility"]+TheoryCraft_Outfits[outfit].agility end
480 if (TheoryCraft_Outfits[outfit].stamina) then TheoryCraft_Data.Stats["stamina"] = TheoryCraft_Data.Stats["stamina"]+TheoryCraft_Outfits[outfit].stamina end
481 if (TheoryCraft_Outfits[outfit].intellect) then TheoryCraft_Data.Stats["intellect"] = TheoryCraft_Data.Stats["intellect"]+TheoryCraft_Outfits[outfit].intellect end
482 if (TheoryCraft_Outfits[outfit].spirit) then TheoryCraft_Data.Stats["spirit"] = TheoryCraft_Data.Stats["spirit"]+TheoryCraft_Outfits[outfit].spirit end
483 if (TheoryCraft_Outfits[outfit].totalmana) then TheoryCraft_Data.Stats["totalmana"] = TheoryCraft_Data.Stats["totalmana"]+TheoryCraft_Outfits[outfit].totalmana end
484 if (TheoryCraft_Outfits[outfit].totalhealth) then TheoryCraft_Data.Stats["totalhealth"] = TheoryCraft_Data.Stats["totalhealth"]+TheoryCraft_Outfits[outfit].totalhealth end
485  
486 local i = 1
487 TheoryCraft_Data.DequippedSets = {}
488 while (TheoryCraft_Outfits[outfit].destat[i]) do
489 TheoryCraft_Data.Stats = TheoryCraft_DequipEffect(TheoryCraft_Outfits[outfit].destat[i], TheoryCraft_Data.Stats, TheoryCraft_Data.DequippedSets)
490 i = i + 1
491 end
492  
493 local returndata
494 for k,count in pairs(TheoryCraft_Data.DequippedSets) do
495 if TheoryCraft_SetBonuses[k] then
496 for k,v in pairs(TheoryCraft_SetBonuses[k]) do
497 if (v["pieces"] <= count) then
498 returndata = {}
499 returndata = TheoryCraft_DequipLine(v["text"], returndata)
500 for k,v in pairs(returndata) do
501 TheoryCraft_Data.Stats[k] = (TheoryCraft_Data.Stats[k] or 0) + v
502 end
503 returndata = {}
504 returndata = TheoryCraft_DequipSpecial(v["text"], returndata)
505 for k,v in pairs(returndata) do
506 TheoryCraft_Data.Stats[k] = (TheoryCraft_Data.Stats[k] or 0) + v
507 end
508 end
509 end
510 end
511 end
512  
513 if catform or bearform then TheoryCraft_Data.Stats["attackpower"] = TheoryCraft_Data.Stats["attackpower"] + TheoryCraft_Data.Stats["formattackpower"] end
514 TheoryCraft_Data.Stats["strength"] = math.floor(TheoryCraft_Data.Stats["strength"] * talents["strmultiplier"])
515 TheoryCraft_Data.Stats["agility"] = math.floor(TheoryCraft_Data.Stats["agility"] * talents["agimultiplier"])
516 TheoryCraft_Data.Stats["rangedattackpower"] = math.floor(TheoryCraft_Data.Stats["rangedattackpower"]+TheoryCraft_Data.Stats["agilityapranged"]*TheoryCraft_Data.Stats["agility"])
517 TheoryCraft_Data.Stats["attackpower"] = math.floor(TheoryCraft_Data.Stats["attackpower"]+TheoryCraft_Data.Stats["strengthapmelee"]*TheoryCraft_Data.Stats["strength"]+TheoryCraft_Data.Stats["agilityapmelee"]*TheoryCraft_Data.Stats["agility"])
518 TheoryCraft_Data.Stats["intellect"] = math.floor(TheoryCraft_Data.Stats["intellect"] * talents["intmultiplier"])
519 TheoryCraft_Data.Stats["stamina"] = math.floor(TheoryCraft_Data.Stats["stamina"] * talents["stammultiplier"])
520 TheoryCraft_Data.Stats["spirit"] = math.floor(TheoryCraft_Data.Stats["spirit"] * talents["spiritmultiplier"])
521 TheoryCraft_Data.Stats["totalhealth"] = (TheoryCraft_Data.Stats["totalhealth"] + TheoryCraft_Data.Stats["stamina"]*10)*talents["healthmultiplier"]
522 TheoryCraft_Data.Stats["totalmana"] = (TheoryCraft_Data.Stats["totalmana"] + TheoryCraft_Data.Stats["intellect"]*15)*talents["manamultiplier"]
523 TheoryCraft_Data.Stats["meleecritchance"] = TheoryCraft_Data.Stats["meleecritchance"]+TheoryCraft_Data.Stats["agility"]/TheoryCraft_Data.Stats["agipercrit"]
524 TheoryCraft_Data.Stats["rangedcritchance"] = TheoryCraft_Data.Stats["meleecritchance"]+(talents["Huntercritchance"] or 0)
525 TheoryCraft_Data.Stats["critchance"] = TheoryCraft_Data.Stats["intellect"]/TheoryCraft_intpercrit()+TheoryCraft_CritChance[class][4]
526 if class == "MAGE" then
527 TheoryCraft_Data.Stats["regenfromspirit"] = TheoryCraft_Data.Stats["spirit"]/8+6.25
528 elseif class == "PRIEST" then
529 TheoryCraft_Data.Stats["regenfromspirit"] = TheoryCraft_Data.Stats["spirit"]/8+6.25
530 elseif class == "WARLOCK" then
531 TheoryCraft_Data.Stats["regenfromspirit"] = TheoryCraft_Data.Stats["spirit"]/10+7.5
532 elseif class == "DRUID" then
533 TheoryCraft_Data.Stats["regenfromspirit"] = TheoryCraft_Data.Stats["spirit"]/10+7.5
534 elseif class == "SHAMAN" then
535 TheoryCraft_Data.Stats["regenfromspirit"] = TheoryCraft_Data.Stats["spirit"]/10+8.5
536 elseif class == "HUNTER" then
537 TheoryCraft_Data.Stats["regenfromspirit"] = TheoryCraft_Data.Stats["spirit"]/10+7.5
538 elseif class == "PALADIN" then
539 TheoryCraft_Data.Stats["regenfromspirit"] = TheoryCraft_Data.Stats["spirit"]/10+7.5
540 elseif class == "ROGUE" then
541 TheoryCraft_Data.Stats["regenfromspirit"] = 0
542 elseif class == "WARRIOR" then
543 TheoryCraft_Data.Stats["regenfromspirit"] = 0
544 end
545  
546 TheoryCraft_Data.Stats["meleecritchancereal"] = TheoryCraft_Data.Stats["meleecritchance"]+(remove or 0)
547 if (TheoryCraft_Data.EquipEffects["FistEquipped"] or 0) >= 1 then
548 TheoryCraft_Data.Stats["meleecritchance"] = TheoryCraft_Data.Stats["meleecritchance"]+TheoryCraft_GetStat("Fistspec")
549 end
550 if (TheoryCraft_Data.EquipEffects["DaggerEquipped"] or 0) >= 1 then
551 TheoryCraft_Data.Stats["meleecritchance"] = TheoryCraft_Data.Stats["meleecritchance"]+TheoryCraft_GetStat("Daggerspec")
552 end
553 if (TheoryCraft_Data.EquipEffects["AxeEquipped"] or 0) >= 1 then
554 TheoryCraft_Data.Stats["meleecritchance"] = TheoryCraft_Data.Stats["meleecritchance"]+TheoryCraft_GetStat("Axespec")
555 end
556 if (TheoryCraft_Data.EquipEffects["PolearmEquipped"] or 0) >= 1 then
557 TheoryCraft_Data.Stats["meleecritchance"] = TheoryCraft_Data.Stats["meleecritchance"]+TheoryCraft_GetStat("Polearmspec")
558 end
559 local meleeapmult = TheoryCraft_GetStat("MeleeAPMult")
560 if meleeapmult > 3 then
561 TheoryCraft_Data.Stats["Meleemodifier"] = (talents["Twohandmodifier"] or 0)+(talents["Twohandtalentmod"] or 0)
562 elseif meleeapmult > 1 then
563 TheoryCraft_Data.Stats["Meleemodifier"] = (talents["Onehandmodifier"] or 0)+(talents["Onehandtalentmod"] or 0)
564 end
565 local manaregen = TheoryCraft_GetStat("manaperfive")/5
566 manaregen = manaregen+TheoryCraft_Data.Stats["totalmana"]*TheoryCraft_GetStat("FelEnergy")/4
567 TheoryCraft_Data.Stats["regen"] = manaregen+TheoryCraft_Data.Stats["regenfromspirit"]
568 TheoryCraft_Data.Stats["icregen"] = manaregen+(TheoryCraft_Data.Stats["regenfromspirit"])*TheoryCraft_GetStat("ICPercent")
569 if (class == "MAGE") then
570 TheoryCraft_Data.Stats["maxtotalmana"] = TheoryCraft_Data.Stats["totalmana"]+TheoryCraft_Data.Stats["regenfromspirit"]*15*8+1100+manaregen*8
571 end
572 if (class == "WARLOCK") then
573 getlifetap(TheoryCraft_Data.Stats)
574 end
575  
576 TheoryCraft_Data.Stats["All"] = math.floor(TheoryCraft_Data.Stats["spirit"]*(talents["Allspiritual"] or 0))
577 TheoryCraft_Data.Stats["BlockValue"] = TheoryCraft_GetStat("BlockValueReport")+(TheoryCraft_Data.Stats["strength"]/20) - 1
578 end
579  
580 local function AddProcs(casttime, returndata, spelldata)
581 TheoryCraft_Data.Procs = {}
582 if TheoryCraft_Settings["procs"] == nil then return end
583 if (spelldata == nil) or (spelldata.Schools == nil) then return end
584 if TheoryCraft_Data.EquipEffects["procs"] then
585 local i = 1
586 local amount, procduration
587 while TheoryCraft_Data.EquipEffects["procs"][i] do
588 amount = TheoryCraft_Data.EquipEffects["procs"][i].amount
589 if TheoryCraft_Data.EquipEffects["procs"][i].exact then
590 procduration = 1 - (1 - TheoryCraft_Data.EquipEffects["procs"][i].proc)^math.floor(TheoryCraft_Data.EquipEffects["procs"][i].duration/casttime)
591 else
592 procduration = 1 - (1 - TheoryCraft_Data.EquipEffects["procs"][i].proc)^(TheoryCraft_Data.EquipEffects["procs"][i].duration/casttime)
593 end
594 TheoryCraft_Data.Procs[TheoryCraft_Data.EquipEffects["procs"][i].type] = (TheoryCraft_Data.Procs[TheoryCraft_Data.EquipEffects["procs"][i].type] or 0)+amount*procduration
595 i = i + 1
596 end
597 i = 1
598 while (spelldata.Schools[i]) do
599 TheoryCraft_AddData(spelldata.Schools[i], TheoryCraft_Data.Procs, returndata)
600 i = i+1
601 end
602 if TheoryCraft_Data.Procs["ICPercent"] then
603 TheoryCraft_Data.Stats["icregen"] = TheoryCraft_GetStat("manaperfive")/5+(TheoryCraft_Data.Stats["regenfromspirit"])*(TheoryCraft_GetStat("ICPercent")+TheoryCraft_Data.Procs["ICPercent"])
604 end
605 end
606 end
607  
608 local function CleanUp(spelldata, returndata)
609 if spelldata.percent == 0 then
610 returndata["plusdam"] = nil
611 returndata["damfinal"] = nil
612 returndata["damcoef"] = nil
613 end
614 if spelldata.ismelee then
615 returndata["manacost"] = nil
616 returndata["plusdam"] = nil
617 end
618 if spelldata.isheal then
619 returndata["penetration"] = nil
620 end
621 if spelldata.armor then
622 returndata["plusdam"] = nil
623 returndata["penetration"] = nil
624 end
625 if spelldata.dodps == nil then
626 returndata["hps"] = nil
627 returndata["withhothps"] = nil
628 returndata["hpsdam"] = nil
629 returndata["hpsdampercent"] = nil
630 returndata["dps"] = nil
631 returndata["withdotdps"] = nil
632 returndata["dpsdam"] = nil
633 returndata["dpsdampercent"] = nil
634 end
635 if (spelldata.usemelee) or (spelldata.petspell) then
636 returndata["nextpendam"] = nil
637 returndata["nextpen"] = nil
638 returndata["penetration"] = nil
639 end
640 if spelldata.petspell then
641 returndata["damcoef"] = nil
642 returndata["dpsdam"] = nil
643 returndata["dpsdampercent"] = nil
644 returndata["plusdam"] = nil
645 returndata["dameff"] = nil
646 returndata["damfinal"] = nil
647 returndata["lifetapdps"] = nil
648 returndata["lifetapdpm"] = nil
649 returndata["nextagidps"] = nil
650 returndata["nexthitdps"] = nil
651 returndata["nextcritdps"] = nil
652 returndata["nextstrdpsequive"] = nil
653 returndata["nextagidpsequive"] = nil
654 returndata["nexthitdpsequive"] = nil
655 returndata["nextcritdpsequive"] = nil
656 returndata["nextagidam"] = nil
657 returndata["nextpendam"] = nil
658 returndata["nexthitdam"] = nil
659 returndata["nextcritdam"] = nil
660 returndata["nextstrdamequive"] = nil
661 returndata["nextagidamequive"] = nil
662 returndata["nextpendamequive"] = nil
663 returndata["nexthitdamequive"] = nil
664 returndata["nextcritdamequive"] = nil
665 returndata["regendam"] = nil
666 returndata["icregendam"] = nil
667 returndata["nextcritheal"] = nil
668 returndata["nextcrithealequive"] = nil
669 returndata["hpsdam"] = nil
670 returndata["hpsdampercent"] = nil
671 returndata["regenheal"] = nil
672 returndata["icregenheal"] = nil
673 end
674  
675 if (spelldata.dontdpsafterresists) then
676 returndata["nexthitdam"] = nil
677 end
678  
679 if (spelldata.cancrit == nil) then
680 returndata["nextcritdam"] = nil
681 returndata["nextcritdamequive"] = nil
682 returndata["nextcritdps"] = nil
683 returndata["nextcritdpsequive"] = nil
684 returndata["critchance"] = nil
685 returndata["critdmgchance"] = nil
686 returndata["crithealchance"] = nil
687 returndata["critdmgmin"] = nil
688 returndata["critdmgmax"] = nil
689 returndata["critdmgminminusignite"] = nil
690 returndata["critdmgmaxminusignite"] = nil
691 returndata["crithealmin"] = nil
692 returndata["crithealmax"] = nil
693 end
694 end
695  
696 local function GenerateTooltip(frame, returndata, spelldata, spellrank)
697 returndata["RangedAPMult"] = 2.8
698 if (frame == nil) or (frame:NumLines() == 0) then
699 CleanUp(spelldata, returndata)
700 return
701 end
702 if spelldata.evocation then
703 CleanUp(spelldata, returndata)
704 returndata["evocation"] = TheoryCraft_GetStat("maxtotalmana")-TheoryCraft_GetStat("totalmana")-1100
705 return
706 end
707 if (spelldata.isranged) then
708 if TheoryCraft_Data.EquipEffects["RangedSpeed"] == nil then
709 CleanUp(spelldata, returndata)
710 return
711 end
712 end
713 if (spelldata.isseal) then
714 if TheoryCraft_Data.EquipEffects["MainSpeed"] == nil then
715 CleanUp(spelldata, returndata)
716 return
717 end
718 end
719 if (spelldata.id == "Backstab") then
720 if TheoryCraft_GetStat("DaggerEquipped") == 0 then
721 CleanUp(spelldata, returndata)
722 return
723 end
724 end
725 if (spelldata.ismelee) then
726 if TheoryCraft_Data.EquipEffects["MainSpeed"] == nil then
727 CleanUp(spelldata, returndata)
728 return
729 end
730 local i = 1
731 returndata["critchance"] = TheoryCraft_Data.Stats["meleecritchance"]+TheoryCraft_GetStat(spelldata.id.."critchance")
732 while spelldata.Schools[i] do
733 returndata["critchance"] = returndata["critchance"]+TheoryCraft_GetStat(spelldata.Schools[i].."critchance")
734 i = i + 1
735 end
736 end
737 if (spelldata.bearform) then
738 local _, _, active = GetShapeshiftFormInfo(1)
739 if active == nil then
740 CleanUp(spelldata, returndata)
741 return
742 end
743 end
744 if (spelldata.catform) then
745 local _, _, active = GetShapeshiftFormInfo(3)
746 if active == nil then
747 CleanUp(spelldata, returndata)
748 return
749 end
750 end
751 if (spelldata.usemelee) then
752 returndata["critchance"] = (TheoryCraft_Data.Stats["meleecritchance"] or 0)+TheoryCraft_GetStat("Holycritchance")
753 returndata["critbonus"] = 1
754 end
755 if (spelldata.isranged) or ((class == "HUNTER") and (spelldata.ismelee == nil)) then
756 returndata["critchance"] = TheoryCraft_Data.Stats["rangedcritchance"]
757 end
758 returndata["description"] = getglobal(frame:GetName().."TextLeft"..frame:NumLines()):GetText()
759 returndata["casttime"] = getcasttime(frame)+(returndata["casttime"] or 0)
760 returndata["manacost"] = getmanacost(frame)
761 if not (spelldata.shoot or spelldata.ismelee or spelldata.isranged) then
762 returndata["basemanacost"] = returndata["manacost"]
763 end
764 if returndata["casttime"] < 1.5 then
765 returndata["casttime"] = 1.5
766 end
767 returndata["regencasttime"] = returndata["casttime"]
768 if (spelldata.casttime) then
769 returndata["casttime"] = spelldata.casttime
770 end
771 AddProcs(returndata["casttime"], returndata, spelldata)
772 if (spelldata.regencasttime) then
773 returndata["regencasttime"] = spelldata.regencasttime
774 end
775 if (returndata["netherwind"] == 1) and (TheoryCraft_Settings["procs"]) then
776 if (returndata["casttime"] > 1.5) then returndata["casttime"] = (returndata["casttime"]-1.5)*0.9+1.5 end
777 if (returndata["regencasttime"] > 1.5) then returndata["regencasttime"] = (returndata["regencasttime"]-1.5)*0.9+1.5 end
778 end
779 local spelllevel = 60
780 local levelpercent = 1
781 returndata["manamultiplier"] = spelldata.manamultiplier
782 if (spelldata["level"..spellrank]) then spelllevel = spelldata["level"..spellrank] end
783 if (spelldata["level"..spellrank.."per"]) then levelpercent = spelldata["level"..spellrank.."per"] end
784 if (spelldata["level"..spellrank.."manamult"]) then returndata["manamultiplier"] = spelldata["level"..spellrank.."manamult"] end
785 if (spelldata["level"..spellrank.."ct"]) then
786 returndata["casttime"] = spelldata["level"..spellrank.."ct"]
787 returndata["regencasttime"] = spelldata["level"..spellrank.."ct"]
788 end
789 if (spelllevel < 20) then
790 levelpercent = levelpercent*(0.0375*spelllevel+0.25)
791 end
792  
793 returndata["dotduration"] = TheoryCraft_getDotDuration(returndata["description"])
794 returndata["basedotduration"] = spelldata.basedotduration
795 if (spelldata.ismelee == nil) and (spelldata.isranged == nil) then
796 if (spelldata.isheal == nil) and (spelldata.talentsbeforegear == nil) then
797 returndata["damcoef"] = spelldata.percent*returndata["tmpincrease"]*returndata["tmpincreaseupfront"]*levelpercent
798 else
799 returndata["damcoef"] = spelldata.percent*levelpercent
800 end
801 if (spelldata.righteousness) then
802 if (TheoryCraft_Data.EquipEffects["MeleeAPMult"] >= 3) then
803 returndata["damcoef"] = spelldata.percent2*returndata["tmpincrease"]*levelpercent
804 end
805 end
806 if (spelldata.hasdot == 1) then
807 returndata["damcoef2"] = spelldata.percentdot
808 returndata["plusdam2"] = math.floor(returndata["plusdam"] * returndata["damcoef2"] * levelpercent)
809 end
810 if (newcasttime) and (spelldata.isdot) then
811 returndata["damcoef"] = returndata["damcoef"]*newcasttime/returndata["basedotduration"]
812 returndata["casttime"] = newcasttime
813 end
814 returndata["damfinal"] = returndata["plusdam"] * returndata["damcoef"]
815 end
816  
817 if returndata["critchance"] > 100 then
818 returndata["critchance"] = 100
819 end
820 returndata["critbonus"] = returndata["critbonus"]+returndata["sepignite"]*(returndata["baseincrease"]+returndata["ignitemodifier"]-1)
821 returndata["sepignite"] = returndata["sepignite"]*returndata["baseincrease"]
822  
823 returndata["talentbaseincrease"] = (1/returndata["tmpincrease"])*(returndata["talentmod"]+returndata["tmpincrease"])
824 returndata["talentbaseincreaseupfront"] = (1/returndata["tmpincreaseupfront"])*(returndata["talentmodupfront"]+returndata["tmpincreaseupfront"])
825 if (spelldata.talentsbeforegear == nil) and (returndata["damcoef"]) then
826 returndata["damcoef"] = returndata["damcoef"]*returndata["talentbaseincrease"]*returndata["talentbaseincreaseupfront"]
827 end
828 if class == "DRUID" then
829 local _, bearform, catform
830 _, _, bearform = GetShapeshiftFormInfo(1)
831 _, _, catform = GetShapeshiftFormInfo(3)
832 if catform then
833 TheoryCraft_Data.EquipEffects["MeleeAPMult"] = 1
834 TheoryCraft_Data.EquipEffects["MainSpeed"] = 1
835 elseif bearform then
836 TheoryCraft_Data.EquipEffects["MeleeAPMult"] = 2.5
837 TheoryCraft_Data.EquipEffects["MainSpeed"] = 2.5
838 end
839 if (bearform) or (catform) then
840 local lowDmg, hiDmg, offlowDmg, offhiDmg, posBuff, negBuff, percentmod = UnitDamage("player")
841 local base, pos, neg = UnitAttackPower("player")
842 base = (base+pos+neg)/14*TheoryCraft_Data.EquipEffects["MeleeAPMult"]
843 TheoryCraft_Data.EquipEffects["MeleeMin"] = lowDmg-base
844 TheoryCraft_Data.EquipEffects["MeleeMax"] = hiDmg-lowDmg+TheoryCraft_Data.EquipEffects["MeleeMin"]
845 end
846 end
847 TheoryCraft_getMinMax(spelldata, returndata, frame)
848 if spelldata.cancrit then
849 if spelldata.drain then
850 returndata["critdmgchance"] = returndata["critchance"]
851 returndata["crithealchance"] = returndata["critchance"]
852 elseif spelldata.isheal then
853 returndata["crithealchance"] = returndata["critchance"]
854 else
855 returndata["critdmgchance"] = returndata["critchance"]
856 end
857 end
858  
859 if spelldata.isheal == nil then
860 returndata["manacost"] = returndata["manacost"]-returndata["manacost"]*(TheoryCraft_Data.Talents["clearcast"] or 0)
861 end
862 if (returndata["manamultiplier"]) then
863 returndata["manacost"] = returndata["manacost"]*returndata["manamultiplier"]
864 end
865 returndata["manacost"] = returndata["manacost"]-TheoryCraft_Data.Stats["icregen"]*returndata["regencasttime"]
866 returndata["manacost"] = returndata["manacost"]*returndata["manacostmod"]
867  
868 if (returndata["crithealchance"]) and (returndata["crithealchance"] > 100) then
869 returndata["crithealchance"] = 100
870 end
871 if (returndata["critdmgchance"]) and (returndata["critdmgchance"] > 100) then
872 returndata["critdmgchance"] = 100
873 end
874  
875 if spelldata.dontusemelee then
876 returndata["critbonus"] = 0.5
877 end
878 if (spelldata.isseal) or (spelldata.ismelee) or (spelldata.isranged) then
879 if (returndata["mindamage"] and returndata["maxdamage"] and (spelldata.isseal == nil)) and (spelldata.block == nil) then
880 returndata["critdmgmin"] = returndata["mindamage"]*(returndata["critbonus"]+1)
881 returndata["critdmgmax"] = returndata["maxdamage"]*(returndata["critbonus"]+1)
882 returndata["averagedamnocrit"] = (returndata["maxdamage"]+returndata["mindamage"])/2
883 returndata["averagecritdam"] = returndata["averagedamnocrit"]*returndata["critbonus"]
884 returndata["averagedam"] = returndata["averagedamnocrit"]+returndata["averagecritdam"]*returndata["critdmgchance"]/100
885 returndata["nextagidam"] = 10*TheoryCraft_Data.Talents["agimultiplier"]
886 if spelldata.ismelee then
887 if spelldata.nextattack then
888 local attackpower = 10*TheoryCraft_Data.Talents["agimultiplier"]*TheoryCraft_Data.Stats["agilityapmelee"]
889 local addeddamage = attackpower*(TheoryCraft_Data.EquipEffects["MainSpeed"])*returndata["backstabmult"]*returndata["baseincrease"]*TheoryCraft_GetStat("Meleemodifier")/14
890 local addedcritpercent = 10*TheoryCraft_Data.Talents["agimultiplier"]/TheoryCraft_Data.Stats["agipercrit"]/100
891 returndata["nextagidam"] = addedcritpercent*returndata["averagecritdam"]+addeddamage*(addedcritpercent+returndata["critdmgchance"]/100)*returndata["critbonus"]+addeddamage
892 returndata["damworth"] = (1+(returndata["critchance"]/100)*returndata["critbonus"])*(TheoryCraft_Data.EquipEffects["MainSpeed"])/14*returndata["backstabmult"]*returndata["baseincrease"]*TheoryCraft_GetStat("Meleemodifier")
893 elseif returndata["bloodthirstmult"] then
894 local attackpower = 10*TheoryCraft_Data.Talents["agimultiplier"]*TheoryCraft_Data.Stats["agilityapmelee"]
895 local addeddamage = attackpower*returndata["bloodthirstmult"]*returndata["backstabmult"]*returndata["baseincrease"]*TheoryCraft_GetStat("Meleemodifier")/14
896 local addedcritpercent = 10*TheoryCraft_Data.Talents["agimultiplier"]/TheoryCraft_Data.Stats["agipercrit"]/100
897 returndata["nextagidam"] = addedcritpercent*returndata["averagecritdam"]+addeddamage*(addedcritpercent+returndata["critdmgchance"]/100)*returndata["critbonus"]+addeddamage
898 returndata["damworth"] = (1+(returndata["critchance"]/100)*returndata["critbonus"])*returndata["bloodthirstmult"]*returndata["backstabmult"]*returndata["baseincrease"]*TheoryCraft_GetStat("Meleemodifier")
899 else
900 local attackpower = 10*TheoryCraft_Data.Talents["agimultiplier"]*TheoryCraft_Data.Stats["agilityapmelee"]
901 local addeddamage = attackpower*TheoryCraft_Data.EquipEffects["MeleeAPMult"]*returndata["backstabmult"]*returndata["baseincrease"]*TheoryCraft_GetStat("Meleemodifier")/14
902 local addedcritpercent = 10*TheoryCraft_Data.Talents["agimultiplier"]/TheoryCraft_Data.Stats["agipercrit"]/100
903 returndata["nextagidam"] = addedcritpercent*returndata["averagecritdam"]+addeddamage*(addedcritpercent+returndata["critdmgchance"]/100)*returndata["critbonus"]+addeddamage
904 returndata["damworth"] = (1+(returndata["critchance"]/100)*returndata["critbonus"])*TheoryCraft_Data.EquipEffects["MeleeAPMult"]/14*returndata["backstabmult"]*returndata["baseincrease"]*TheoryCraft_GetStat("Meleemodifier")
905 end
906 returndata["nextstrdam"] = 10*TheoryCraft_Data.Talents["strmultiplier"]*TheoryCraft_Data.Stats["strengthapmelee"]*returndata["damworth"]
907 else
908 local attackpower = 10*TheoryCraft_Data.Talents["agimultiplier"]*TheoryCraft_Data.Stats["agilityapranged"]
909 local addeddamage = attackpower*returndata["RangedAPMult"]*returndata["backstabmult"]*returndata["baseincrease"]*TheoryCraft_GetStat("Rangedmodifier")/14
910 local addedcritpercent = 10*TheoryCraft_Data.Talents["agimultiplier"]/TheoryCraft_Data.Stats["agipercrit"]/100
911 returndata["nextagidam"] = addedcritpercent*returndata["averagecritdam"]+addeddamage*(addedcritpercent+returndata["critdmgchance"]/100)*returndata["critbonus"]+addeddamage
912 returndata["damworth"] = (1+(returndata["critchance"]/100)*returndata["critbonus"])*returndata["RangedAPMult"]/14*returndata["backstabmult"]*returndata["baseincrease"]*TheoryCraft_GetStat("Rangedmodifier")
913 end
914  
915 returndata["nextcritdam"] = returndata["averagecritdam"]/100
916 returndata["nexthitdam"] = returndata["averagedamnocrit"]/100
917 if (returndata["damworth"] ~= 0) then
918 if returndata["nextstrdam"] then
919 returndata["nextstrdamequive"] = returndata["nextstrdam"]/returndata["damworth"]
920 end
921 returndata["nexthitdamequive"] = returndata["nexthitdam"]/returndata["damworth"]
922 returndata["nextcritdamequive"] = returndata["nextcritdam"]/returndata["damworth"]
923 returndata["nextagidamequive"] = returndata["nextagidam"]/returndata["damworth"]
924 end
925 if (spelldata.isranged) and (spelldata.shoot == nil) then
926 if (spelldata.autoshot) then
927 returndata["dpm"] = returndata["msrotationlength"]*returndata["msrotationdps"]/returndata["manacost"]
928 returndata["maxoomdam"] = (TheoryCraft_Data.Stats["totalmana"]+TheoryCraft_GetStat("manarestore"))*returndata["dpm"]
929 returndata["maxoomdamtime"] = returndata["maxoomdam"]/returndata["dps"]
930 returndata["regendam"] = TheoryCraft_Data.Stats["regen"]*10*returndata["dpm"]
931 returndata["icregendam"] = TheoryCraft_Data.Stats["icregen"]*10*returndata["dpm"]
932 else
933 if TheoryCraft_Settings["dontcritdpm"] then
934 returndata["dpm"] = returndata["averagedamnocrit"]/returndata["manacost"]
935 else
936 returndata["dpm"] = returndata["averagedam"]/returndata["manacost"]
937 end
938 returndata["regendam"] = TheoryCraft_Data.Stats["regen"]*10*returndata["dpm"]
939 returndata["icregendam"] = TheoryCraft_Data.Stats["icregen"]*10*returndata["dpm"]
940 end
941 end
942 end
943 else
944 if class == "DRUID" then
945 if (spelldata.cancrit) and (returndata["grace"] ~= 0) and (not TheoryCraft_Settings["dontcrit"]) then
946 returndata["casttime"] = returndata["casttime"]-(returndata["critchance"]/100)*returndata["grace"]
947 if returndata["casttime"] < 1.5 then
948 returndata["casttime"] = 1.5
949 end
950 end
951 end
952 if (class == "MAGE") then
953 if (returndata["critdmgchance"]) and (not TheoryCraft_Settings["dontcrit"]) then
954 returndata["manacost"] = returndata["manacost"]-returndata["manacost"]*((returndata["critdmgchance"]/100)*returndata["illum"])
955 end
956 end
957  
958 if returndata["mindamage"] then
959 if returndata["maxdamage"] == nil then
960 returndata["maxdamage"] = returndata["mindamage"]
961 end
962 returndata["critdmgmin"] = returndata["mindamage"]*(returndata["critbonus"]+1)
963 returndata["critdmgmax"] = returndata["maxdamage"]*(returndata["critbonus"]+1)
964 returndata["averagedamnocrit"] = (returndata["maxdamage"]+returndata["mindamage"])/2
965 returndata["averagedpsdamnocrit"] = returndata["damfinal"]
966 if spelldata.cancrit then
967 returndata["critdmgmin"] = returndata["mindamage"]*(returndata["critbonus"]+1)
968 returndata["critdmgmax"] = returndata["maxdamage"]*(returndata["critbonus"]+1)
969 if (returndata["sepignite"] ~= 0) then
970 returndata["critdmgminminusignite"] = ((returndata["critdmgmin"]/(returndata["critbonus"]+1))*(1+returndata["critbonus"]-returndata["sepignite"]))
971 returndata["critdmgmaxminusignite"] = ((returndata["critdmgmax"]/(returndata["critbonus"]+1))*(1+returndata["critbonus"]-returndata["sepignite"]))
972 end
973  
974 if (TheoryCraft_Settings["rollignites"]) and (not spelldata.dontdomax) and (returndata["sepignite"] ~= 0) and (returndata["critdmgchance"] < 99) then
975 local ignitecritmin = returndata["critdmgmin"]-(returndata["critdmgmin"]/(returndata["critbonus"]+1))*(1+returndata["critbonus"]-returndata["sepignite"])
976 local ignitecritmax = returndata["critdmgmax"]-(returndata["critdmgmax"]/(returndata["critbonus"]+1))*(1+returndata["critbonus"]-returndata["sepignite"])
977 local igniteaverage = (ignitecritmax-ignitecritmin)/2+ignitecritmin
978 local noignitecritmin = returndata["critdmgmin"]-ignitecritmin-returndata["mindamage"]
979 local noignitecritmax = returndata["critdmgmax"]-ignitecritmax-returndata["maxdamage"]
980 local noigniteaverage = (noignitecritmin+noignitecritmax)/2
981 local rollchance = (returndata["critdmgchance"]/100)
982 local ignitelength = 4+rollchance*4+(rollchance^2)*4+(rollchance^3)*4+(rollchance^4)*4+(rollchance^5)*4+(rollchance^6)*4
983 returndata["averagecritdam"] = noigniteaverage+ignitelength*igniteaverage/4
984 rollchance = ((returndata["critdmgchance"]+1)/100)
985 local newignitelength = 4+rollchance*4+(rollchance^2)*4+(rollchance^3)*4+(rollchance^4)*4+(rollchance^5)*4+(rollchance^6)*4
986 -- Average Crit Damage
987 returndata["nextcritdam"] = noigniteaverage+newignitelength*igniteaverage/4
988 -- Damage from extra ignite length
989 returndata["nextcritdam"] = (returndata["nextcritdam"]+(newignitelength-ignitelength)*igniteaverage/4*returndata["critdmgchance"])/100
990 else
991 returndata["averagecritdam"] = returndata["averagedamnocrit"]*returndata["critbonus"]
992 returndata["nextcritdam"] = returndata["averagecritdam"]/100
993 end
994 returndata["damhitworth"] = returndata["damcoef"]
995 returndata["damcritworth"] = returndata["damcoef"]*(returndata["critbonus"]+1)
996 returndata["damworth"] = returndata["damcoef"]*(1+returndata["critdmgchance"]*returndata["critbonus"]/100)
997 returndata["averagedam"] = returndata["averagedamnocrit"]+returndata["averagecritdam"]*returndata["critdmgchance"]/100
998 returndata["nextcritdam"] = returndata["nextcritdam"] + returndata["averagedam"]*returndata["grace"]
999 returndata["nextcritdamequive"] = returndata["nextcritdam"]/returndata["damworth"]
1000 else
1001 returndata["averagecritdam"] = 0
1002 returndata["averagedam"] = returndata["averagedamnocrit"]
1003 returndata["damhitworth"] = returndata["damcoef"]
1004 returndata["damcritworth"] = 0
1005 returndata["damworth"] = returndata["damcoef"]
1006 end
1007 returndata["averagedamthreat"] = returndata["averagedam"]*returndata["threat"]
1008 returndata["averagedamthreatpercent"] = returndata["averagedamthreat"]/returndata["averagedam"]*100
1009 if (not TheoryCraft_Settings["dontcrit"]) then
1010 returndata["averagedpsdam"] = returndata["averagedpsdamnocrit"]*(returndata["averagedam"]/returndata["averagedamnocrit"])
1011 else
1012 returndata["averagedpsdam"] = returndata["averagedpsdamnocrit"]
1013 end
1014 if spelldata.tickinterval then
1015 if (spelldata.hasdot) and (returndata["dotdamage"]) then
1016 returndata["averagedamtick"] = returndata["dotdamage"]/returndata["dotduration"]*spelldata.tickinterval
1017 returndata["averagedamticknocrit"] = returndata["dotdamage"]/returndata["dotduration"]*spelldata.tickinterval
1018 else
1019 if returndata["manamultiplier"] then
1020 if (TheoryCraft_Settings["dontcrit"]) then
1021 returndata["averagedamtick"] = returndata["averagedamnocrit"]/returndata["manamultiplier"]/returndata["dotduration"]*spelldata.tickinterval
1022 else
1023 returndata["averagedamtick"] = returndata["averagedam"]/returndata["manamultiplier"]/returndata["dotduration"]*spelldata.tickinterval
1024 end
1025 else
1026 if (TheoryCraft_Settings["dontcrit"]) then
1027 returndata["averagedamtick"] = returndata["averagedamnocrit"]/returndata["dotduration"]*spelldata.tickinterval
1028 else
1029 returndata["averagedamtick"] = returndata["averagedam"]/returndata["dotduration"]*spelldata.tickinterval
1030 end
1031 end
1032 end
1033 end
1034 if spelldata.coa then
1035 local tick1 = round((returndata["averagedam"]-returndata["damfinal"]*returndata["baseincrease"])/24+returndata["damfinal"]*returndata["baseincrease"]/12)
1036 local tick2 = round((returndata["averagedam"]-returndata["damfinal"]*returndata["baseincrease"])/12+returndata["damfinal"]*returndata["baseincrease"]/12)
1037 local tick3 = round((returndata["averagedam"]-returndata["damfinal"]*returndata["baseincrease"])/8+returndata["damfinal"]*returndata["baseincrease"]/12)
1038 returndata["averagedamtick"] = tick1..", "..tick2..", "..tick3
1039 end
1040 if spelldata.starshards then
1041 local tick1 = round((returndata["averagedam"]-returndata["damfinal"]*returndata["baseincrease"])/10+returndata["damfinal"]*returndata["baseincrease"]/6)
1042 local tick2 = round((returndata["averagedam"]-returndata["damfinal"]*returndata["baseincrease"])/6+returndata["damfinal"]*returndata["baseincrease"]/6)
1043 local tick3 = round((returndata["averagedam"]-returndata["damfinal"]*returndata["baseincrease"])/4.5+returndata["damfinal"]*returndata["baseincrease"]/6)
1044 returndata["averagedamtick"] = tick1..", "..tick2..", "..tick3
1045 end
1046 if (TheoryCraft_Settings["dontcrit"]) then
1047 returndata["dpm"] = returndata["averagedamnocrit"]/returndata["manacost"]
1048 else
1049 returndata["dpm"] = returndata["averagedam"]/returndata["manacost"]
1050 end
1051 if (TheoryCraft_Data.Stats["lifetapMana"]) and (TheoryCraft_Data.Stats["lifetapHealth"]) then
1052 returndata["lifetapdpm"] = returndata["dpm"]*returndata["manacost"]/(returndata["manacost"]/TheoryCraft_Data.Stats["lifetapMana"]*TheoryCraft_Data.Stats["lifetapHealth"])
1053 end
1054 if (spelldata.overcooldown) then
1055 if (TheoryCraft_Settings["dontcrit"]) then
1056 returndata["dps"] = returndata["averagedamnocrit"]/getcooldown(frame)
1057 else
1058 returndata["dps"] = returndata["averagedam"]/getcooldown(frame)
1059 end
1060 returndata["dpsdam"] = returndata["averagedpsdam"]/getcooldown(frame)
1061 else
1062 if (TheoryCraft_Settings["dotoverct"]) and (spelldata.isdot) then
1063 if (TheoryCraft_Settings["dontcrit"]) then
1064 returndata["dps"] = returndata["averagedamnocrit"]/returndata["casttime"]
1065 else
1066 returndata["dps"] = returndata["averagedam"]/returndata["casttime"]
1067 end
1068 returndata["dpsdam"] = returndata["averagedpsdam"]/returndata["casttime"]
1069 else
1070 if spelldata.isdot then
1071 if (TheoryCraft_Settings["dontcrit"]) then
1072 returndata["dps"] = returndata["averagedamnocrit"]/returndata["dotduration"]
1073 else
1074 returndata["dps"] = returndata["averagedam"]/returndata["dotduration"]
1075 end
1076 returndata["dpsdam"] = returndata["averagedpsdam"]/returndata["dotduration"]
1077 else
1078 if (TheoryCraft_Settings["dontcrit"]) then
1079 returndata["dps"] = returndata["averagedamnocrit"]/returndata["casttime"]
1080 else
1081 returndata["dps"] = returndata["averagedam"]/returndata["casttime"]
1082 end
1083 returndata["dpsdam"] = returndata["averagedpsdam"]/returndata["casttime"]
1084 if TheoryCraft_Data.Stats["lifetapMana"] then
1085 if (TheoryCraft_Settings["dontcrit"]) then
1086 returndata["lifetapdps"] = returndata["averagedamnocrit"]/(returndata["casttime"]+(returndata["manacost"]/TheoryCraft_Data.Stats["lifetapMana"])*1.5)
1087 else
1088 returndata["lifetapdps"] = returndata["averagedam"]/(returndata["casttime"]+(returndata["manacost"]/TheoryCraft_Data.Stats["lifetapMana"])*1.5)
1089 end
1090 end
1091 end
1092 end
1093 end
1094  
1095 if returndata["dotdamage"] then
1096 returndata["withdotdpm"] = (returndata["dpm"]*returndata["manacost"]+returndata["dotdamage"])/returndata["manacost"]
1097 if (TheoryCraft_Settings["combinedot"]) then
1098 if (TheoryCraft_Settings["dontcrit"]) then
1099 returndata["withdotdps"] = (returndata["averagedamnocrit"]+returndata["dotdamage"])/returndata["casttime"]
1100 else
1101 returndata["withdotdps"] = (returndata["averagedam"]+returndata["dotdamage"])/returndata["casttime"]
1102 end
1103 else
1104 returndata["withdotdps"] = returndata["dotdamage"]/returndata["dotduration"]
1105 end
1106 end
1107  
1108 if spelldata.isdot then
1109 returndata["dameff"] = returndata["damcoef"]*returndata["baseincrease"]/returndata["dotduration"]*3.5
1110 else
1111 if returndata["damcoef2"] then
1112 returndata["dameff"] = ((returndata["damcoef"]+returndata["damcoef2"])*returndata["baseincrease"])/returndata["casttime"]*3.5
1113 else
1114 returndata["dameff"] = returndata["damcoef"]*returndata["baseincrease"]/returndata["casttime"]*3.5
1115 end
1116 end
1117 if spelldata.dontdomax == nil then
1118 returndata["maxoomdam"] = (TheoryCraft_Data.Stats["totalmana"]+TheoryCraft_GetStat("manarestore"))*returndata["dpm"]
1119 returndata["maxoomdamtime"] = returndata["maxoomdam"]/returndata["dps"]
1120 if TheoryCraft_Data.Stats["maxtotalmana"] then
1121 returndata["maxevocoomdam"] = (TheoryCraft_Data.Stats["maxtotalmana"]+TheoryCraft_GetStat("manarestore"))*returndata["dpm"]
1122 returndata["maxevocoomdamtime"] = returndata["maxevocoomdam"]/returndata["dps"]+8
1123 end
1124 end
1125 if (spelldata.isdot == nil) then
1126 returndata["nexthitdam"] = returndata["averagedamnocrit"]/100
1127 returndata["nexthitdamequive"] = returndata["nexthitdam"]/returndata["damworth"]
1128 end
1129 returndata["nextpendam"] = returndata["averagedam"]*UnitLevel("player")/2400
1130 returndata["nextpendamequive"] = returndata["nextpendam"]/returndata["damworth"]
1131 returndata["regendam"] = TheoryCraft_Data.Stats["regen"]*10*returndata["dpm"]
1132 returndata["icregendam"] = TheoryCraft_Data.Stats["icregen"]*10*returndata["dpm"]
1133 returndata["penetration"] = returndata["penetration"]/((20/3)*UnitLevel("player"))*returndata["dps"]
1134 if (returndata["manamultiplier"]) and (spelldata.lightningshield == nil) then
1135 returndata["averagedam"] = returndata["averagedam"]/returndata["manamultiplier"]
1136 returndata["averagedamnocrit"] = returndata["averagedamnocrit"]/returndata["manamultiplier"]
1137 returndata["averagedamthreat"] = returndata["averagedamthreat"]/returndata["manamultiplier"]
1138 end
1139 end
1140  
1141 if (returndata["minheal"]) then
1142 if (class == "PALADIN") or (class == "MAGE") then
1143 if (returndata["crithealchance"]) then
1144 if (returndata["illum"] ~= 0) and (returndata["mindamage"]) then
1145 returndata["manacost2"] = returndata["manacost"]
1146 end
1147 returndata["manacost"] = returndata["manacost"]-returndata["manacost"]*((returndata["crithealchance"]/100)*returndata["illum"])
1148 end
1149 end
1150 if returndata["maxheal"] == nil then
1151 returndata["maxheal"] = returndata["minheal"]
1152 end
1153 returndata["averagehealnocrit"] = (returndata["maxheal"]-returndata["minheal"])/2+returndata["minheal"]
1154 returndata["averagehpsdamnocrit"] = returndata["damfinal"]
1155 if spelldata.cancrit then
1156 if returndata["crithealchance"] == nil then returndata["crithealchance"] = 0 end
1157 returndata["crithealmin"] = returndata["minheal"]*(returndata["critbonus"]+1)
1158 returndata["crithealmax"] = returndata["maxheal"]*(returndata["critbonus"]+1)
1159 returndata["averagecritheal"] = returndata["averagehealnocrit"]*returndata["critbonus"]
1160 returndata["nextcrit"] = returndata["averagecritheal"]/100
1161 returndata["healworth"] = returndata["damcoef"]*(1+returndata["crithealchance"]*returndata["critbonus"]/100)
1162 returndata["averageheal"] = returndata["averagehealnocrit"]+returndata["averagecritheal"]*returndata["crithealchance"]/100
1163 returndata["nextcritheal"] = returndata["averagecritheal"]/100
1164 returndata["nextcrithealequive"] = returndata["nextcritheal"]/returndata["healworth"]
1165 else
1166 returndata["averagecritheal"] = 0
1167 returndata["averageheal"] = returndata["averagehealnocrit"]
1168 returndata["healworth"] = returndata["damcoef"]
1169 end
1170 returndata["averagehealthreat"] = returndata["averageheal"]*returndata["threat"]
1171 returndata["averagehealthreatpercent"] = returndata["averagehealthreat"]/returndata["averageheal"]*100
1172 returndata["averagehpsdam"] = returndata["averagehpsdamnocrit"]*(returndata["averageheal"]/returndata["averagehealnocrit"])
1173 if spelldata.tickinterval then
1174 if (spelldata.hasdot) and (returndata["hotheal"]) then
1175 returndata["averagehealtick"] = returndata["hotheal"]/returndata["dotduration"]*spelldata.tickinterval
1176 else
1177 if returndata["manamultiplier"] then
1178 returndata["averagehealtick"] = returndata["averageheal"]/returndata["manamultiplier"]/returndata["dotduration"]*spelldata.tickinterval
1179 else
1180 returndata["averagehealtick"] = returndata["averageheal"]/returndata["dotduration"]*spelldata.tickinterval
1181 end
1182 end
1183 end
1184 if TheoryCraft_Settings["dontcrithpm"] then
1185 returndata["hpm"] = returndata["averagehealnocrit"]/returndata["manacost"]
1186 else
1187 returndata["hpm"] = returndata["averageheal"]/returndata["manacost"]
1188 end
1189 if (TheoryCraft_Data.Stats["lifetapMana"]) and (TheoryCraft_Data.Stats["lifetapHealth"]) then
1190 returndata["lifetaphpm"] = returndata["hpm"]*returndata["manacost"]/(returndata["manacost"]/TheoryCraft_Data.Stats["lifetapMana"]*TheoryCraft_Data.Stats["lifetapHealth"])
1191 end
1192 if (TheoryCraft_Settings["dotoverct"]) and (spelldata.isdot) then
1193 returndata["hps"] = returndata["averageheal"]/returndata["casttime"]
1194 returndata["hpsdam"] = returndata["averagehpsdam"]/returndata["casttime"]
1195 else
1196 if spelldata.isdot then
1197 returndata["hps"] = returndata["averageheal"]/returndata["dotduration"]
1198 returndata["hpsdam"] = returndata["averagehpsdam"]/returndata["dotduration"]
1199 else
1200 returndata["hps"] = returndata["averageheal"]/returndata["casttime"]
1201 returndata["hpsdam"] = returndata["averagehpsdam"]/returndata["casttime"]
1202 end
1203 end
1204 if TheoryCraft_Data.Stats["lifetapMana"] then
1205 returndata["lifetaphps"] = returndata["averageheal"]/(returndata["casttime"]+(returndata["manacost"]/TheoryCraft_Data.Stats["lifetapMana"])*1.5)
1206 end
1207  
1208 if returndata["hotheal"] then
1209 returndata["withhothpm"] = (returndata["hpm"]*returndata["manacost"]+returndata["hotheal"])/returndata["manacost"]
1210 if (TheoryCraft_Settings["combinedot"]) then
1211 returndata["withhothps"] = (returndata["averageheal"]+returndata["hotheal"])/returndata["casttime"]
1212 else
1213 returndata["withhothps"] = returndata["hotheal"]/returndata["dotduration"]
1214 end
1215 end
1216  
1217 if spelldata.isdot then
1218 returndata["dameff"] = returndata["damcoef"]*returndata["baseincrease"]/returndata["dotduration"]*3.5
1219 else
1220 if returndata["damcoef2"] then
1221 returndata["dameff"] = ((returndata["damcoef"]+returndata["damcoef2"])*returndata["baseincrease"])/returndata["casttime"]*3.5
1222 else
1223 returndata["dameff"] = returndata["damcoef"]*returndata["baseincrease"]/returndata["casttime"]*3.5
1224 end
1225 end
1226 if spelldata.dontdomax == nil then
1227 returndata["maxoomheal"] = (TheoryCraft_Data.Stats["totalmana"]+TheoryCraft_GetStat("manarestore"))*returndata["hpm"]
1228 returndata["maxoomhealtime"] = returndata["maxoomheal"]/returndata["hps"]
1229 if returndata["maxtotalmana"] then
1230 returndata["maxevocoomheal"] = TheoryCraft_Data.Stats["maxtotalmana"]*returndata["hpm"]
1231 returndata["maxevocoomhealtime"] = returndata["maxevocoomheal"]/returndata["hps"]+8
1232 end
1233 end
1234 returndata["regenheal"] = TheoryCraft_Data.Stats["regen"]*10*returndata["hpm"]
1235 returndata["icregenheal"] = TheoryCraft_Data.Stats["icregen"]*10*returndata["hpm"]
1236 if returndata["manamultiplier"] then
1237 returndata["averageheal"] = returndata["averageheal"]/returndata["manamultiplier"]
1238 returndata["averagehealnocrit"] = returndata["averagehealnocrit"]/returndata["manamultiplier"]
1239 returndata["averagehealthreat"] = returndata["averagehealthreat"]/returndata["manamultiplier"]
1240 end
1241 end
1242 end
1243 if (returndata["dps"]) then
1244 if (returndata["dpsdam"]) then
1245 returndata["dpsdampercent"] = returndata["dpsdam"]/returndata["dps"]*100
1246 end
1247 end
1248 if (returndata["hps"]) then
1249 if (returndata["hpsdam"]) then
1250 returndata["hpsdampercent"] = returndata["hpsdam"]/returndata["hps"]*100
1251 end
1252 end
1253 if (returndata["manamultiplier"]) then
1254 returndata["manacost"] = returndata["manacost"]/returndata["manamultiplier"]
1255 end
1256 if (spelldata.manamultiplier) and (returndata["damcoef"]) and (spelldata.lightningshield == nil) then
1257 returndata["damcoef"] = returndata["damcoef"]/spelldata.manamultiplier
1258 end
1259  
1260 if (returndata["nextcritdam"]) and (returndata["critdmgchance"]) and (returndata["critdmgchance"] > 99) then
1261 if returndata["critdmgchance"] < 100 then
1262 returndata["nextcritdam"] = returndata["nextcritdam"]*(1 - (returndata["critdmgchance"] - 99))
1263 returndata["nextcritdamequive"] = returndata["nextcritdamequive"]*(1 - (returndata["critdmgchance"] - 99))
1264 else
1265 returndata["nextcritdam"] = 0
1266 returndata["nextcritdamequive"] = 0
1267 end
1268 end
1269 if (returndata["nextcritheal"]) and (returndata["crithealchance"]) and (returndata["crithealchance"] > 99) then
1270 if returndata["crithealchance"] < 100 then
1271 returndata["nextcritheal"] = returndata["nextcritheal"]*(1 - (returndata["crithealchance"] - 99))
1272 returndata["nextcrithealequive"] = returndata["nextcrithealequive"]*(1 - (returndata["crithealchance"] - 99))
1273 else
1274 returndata["nextcritheal"] = 0
1275 returndata["nextcrithealequive"] = 0
1276 end
1277 end
1278  
1279 CleanUp(spelldata, returndata)
1280  
1281 if returndata["basemindamage"] then
1282 if returndata["basemaxdamage"] == nil then
1283 returndata["basemaxdamage"] = returndata["basemindamage"]
1284 end
1285 returndata["damtodouble"] = (returndata["basemindamage"]+returndata["basemaxdamage"])/2/returndata["damcoef"]
1286 end
1287  
1288 if returndata["damcoef"] then returndata["damcoef"] = returndata["damcoef"]*100 end
1289 if returndata["dameff"] then returndata["dameff"] = returndata["dameff"]*100 end
1290  
1291 if returndata["dps"] and returndata["manacost"] then
1292 returndata["dpsmana"] = returndata["dps"]/returndata["manacost"]
1293 end
1294 if returndata["manacost"] then
1295 returndata["maxspellcasts"] = 1+math.floor((TheoryCraft_GetStat("totalmana")-(returndata["basemanacost"] or returndata["manacost"]))/returndata["manacost"])
1296 if returndata["maxoomdam"] then
1297 returndata["maxoomdamfloored"] = returndata["dpm"]*returndata["manacost"]*returndata["maxspellcasts"]
1298 end
1299 if returndata["maxoomheal"] then
1300 returndata["maxoomhealfloored"] = returndata["hpm"]*returndata["manacost"]*returndata["maxspellcasts"]
1301 end
1302 end
1303  
1304 return
1305 end
1306  
1307 function TheoryCraft_GenerateTooltip(frame, spellname, spellrank, i2, showonbutton, macro, force)
1308 local timer = GetTime()
1309 local oldspellname = spellname
1310 local olddesc
1311 if i2 == nil then
1312 if (frame) and (frame ~= TCTooltip2) then
1313 if frame:NumLines() == 0 then return end
1314 i2 = 1
1315 if getglobal(frame:GetName().."TextRight1") and getglobal(frame:GetName().."TextRight1"):IsVisible() then
1316 spellrank = getglobal(frame:GetName().."TextRight1"):GetText()
1317 spellrank = tonumber(findpattern(spellrank, "%d+"))
1318 if spellrank == nil then spellrank = 0 end
1319 else
1320 spellrank = nil
1321 end
1322 if getglobal(frame:GetName().."TextLeft1") and getglobal(frame:GetName().."TextLeft1"):GetText() then
1323 spellname = getglobal(frame:GetName().."TextLeft1"):GetText()
1324 else
1325 spellname = ""
1326 end
1327 local spellname2, spellrank2
1328 while (true) do
1329 spellname2, spellrank2 = GetSpellName(i2,BOOKTYPE_SPELL)
1330 if spellname2 == nil then return end
1331 spellrank2 = tonumber(findpattern(spellrank2, "%d+"))
1332 if spellrank2 == nil then spellrank2 = 0 end
1333 if (spellname == spellname2) and ((spellrank == nil) or (spellrank == spellrank2)) then break end
1334 i2 = i2 + 1
1335 end
1336 if spellname ~= spellname2 then return end
1337 if (spellrank) and (spellrank ~= spellrank2) then return end
1338 if (spellname == "Attack") then spellrank = 0 end
1339 if (spellrank == nil) then
1340 olddesc = getglobal(frame:GetName().."TextLeft"..frame:NumLines()):GetText()
1341 while (spellname == spellname2) do
1342 spellname2, spellrank = GetSpellName(i2,BOOKTYPE_SPELL)
1343 if spellname == nil then return end
1344 spellrank = tonumber(findpattern(spellrank, "%d+"))
1345 if spellrank == nil then spellrank = 0 end
1346 TCTooltip:SetOwner(UIParent,"ANCHOR_NONE")
1347 TCTooltip:SetSpell(i2,BOOKTYPE_SPELL)
1348 if (getglobal("TCTooltipTextLeft"..TCTooltip:NumLines())) and (getglobal("TCTooltipTextLeft"..TCTooltip:NumLines()):GetText() == olddesc) then
1349 break
1350 end
1351 i2 = i2 + 1
1352 end
1353 if (TCTooltip) and (getglobal("TCTooltipTextLeft"..TCTooltip:NumLines())) and (getglobal("TCTooltipTextLeft"..TCTooltip:NumLines()):GetText() ~= olddesc) then
1354 return
1355 end
1356 end
1357 else
1358 i2 = 1
1359 local spellname2, spellrank2
1360 if (string.len(spellrank) == 1) and (string.len(spellname) ~= 13) then
1361 macro = nil
1362 end
1363 if (string.len(spellrank) == 2) and (string.len(spellname) ~= 12) then
1364 macro = nil
1365 end
1366 while (true) do
1367 spellname2, spellrank2 = GetSpellName(i2,BOOKTYPE_SPELL)
1368 if spellname2 == nil then return end
1369 spellrank2 = tonumber(findpattern(spellrank2, "%d+"))
1370 if spellrank2 == nil then spellrank2 = 0 end
1371 if (spellname == spellname2) or ((macro) and (spellname == string.sub(spellname2, 1, string.len(spellname)))) then
1372 spellname = spellname2
1373 if spellrank == spellrank2 then
1374 break
1375 end
1376 end
1377 i2 = i2 + 1
1378 end
1379 if spellname ~= spellname2 then return end
1380 if spellrank ~= spellrank2 then return end
1381 if frame == nil then
1382 frame = TCTooltip
1383 end
1384 frame:SetOwner(UIParent,"ANCHOR_NONE")
1385 frame:SetSpell(i2,BOOKTYPE_SPELL)
1386 if frame:NumLines() == 0 then return end
1387 end
1388 end
1389 if spellname == TheoryCraft_Locale.MinMax.autoshotname then
1390 local highestaimed, highestmulti, highestarcane
1391 local i2 = 1
1392 local spellname, spellrank = GetSpellName(i2,BOOKTYPE_SPELL)
1393 while (spellname) do
1394 spellrank = tonumber(findpattern((spellrank or "0"), "%d+"))
1395 if (spellname == TheoryCraft_Locale.MinMax.aimedshotname) and ((highestaimed == nil) or (highestaimed < spellrank)) then
1396 highestaimed = spellrank
1397 end
1398 if (spellname == TheoryCraft_Locale.MinMax.multishotname) and ((highestmulti == nil) or (highestmulti < spellrank)) then
1399 highestmulti = spellrank
1400 end
1401 if (spellname == TheoryCraft_Locale.MinMax.arcaneshotname) and ((highestarcane == nil) or (highestarcane < spellrank)) then
1402 highestarcane = spellrank
1403 end
1404 i2 = i2 + 1
1405 spellname, spellrank = GetSpellName(i2,BOOKTYPE_SPELL)
1406 end
1407 if (highestaimed) and (TheoryCraft_TooltipData[TheoryCraft_Locale.MinMax.aimedshotname.."("..highestaimed..")"] == nil) then
1408 TheoryCraft_GenerateTooltip(TCTooltip2, TheoryCraft_Locale.MinMax.aimedshotname, highestaimed, nil, nil, nil, true)
1409 end
1410 if (highestmulti) and (TheoryCraft_TooltipData[TheoryCraft_Locale.MinMax.multishotname.."("..highestmulti..")"] == nil) then
1411 TheoryCraft_GenerateTooltip(TCTooltip2, TheoryCraft_Locale.MinMax.multishotname, highestmulti, nil, nil, nil, true)
1412 end
1413 if (highestarcane) and (TheoryCraft_TooltipData[TheoryCraft_Locale.MinMax.arcaneshotname.."("..highestarcane..")"] == nil) then
1414 TheoryCraft_GenerateTooltip(TCTooltip2, TheoryCraft_Locale.MinMax.arcaneshotname, highestarcane, nil, nil, nil, true)
1415 end
1416 end
1417 if (not force) and (TheoryCraft_Settings["GenerateList"] ~= "") and (not string.find(TheoryCraft_Settings["GenerateList"], string.gsub(spellname, "-", "%%-").."%("..spellrank.."%)")) then
1418 return
1419 end
1420 local i
1421 for k, v in pairs(TheoryCraft_Spells[class]) do
1422 if v.name == spellname then
1423 i = v
1424 break
1425 end
1426 end
1427 if not i then return end
1428 -- TheoryCraft_Data.Testing = nil
1429 SummateData(i.id, i.Schools)
1430 olddesc = getglobal(frame:GetName().."TextLeft"..frame:NumLines()):GetText()
1431  
1432 if TheoryCraft_TooltipData[olddesc] == nil then
1433 TheoryCraft_TooltipData[olddesc] = {}
1434 end
1435 TheoryCraft_DeleteTable(TheoryCraft_TooltipData[olddesc])
1436 TheoryCraft_CopyTable(summeddata, TheoryCraft_TooltipData[olddesc])
1437 if TheoryCraft_TooltipData[olddesc]["schools"] == nil then
1438 TheoryCraft_TooltipData[olddesc]["schools"] = {}
1439 end
1440 TheoryCraft_CopyTable(i.Schools, TheoryCraft_TooltipData[olddesc]["schools"])
1441 GenerateTooltip(frame, TheoryCraft_TooltipData[olddesc], i, spellrank)
1442 if macro then
1443 TheoryCraft_TooltipData[oldspellname.."MACRO("..spellrank..")"] = olddesc
1444 end
1445 TheoryCraft_TooltipData[spellname.."("..spellrank..")"] = olddesc
1446 TheoryCraft_TooltipData[olddesc]["basedescription"] = olddesc
1447 if (i.shoot) or (i.ismelee) or (i.isranged) then
1448 if getglobal(frame:GetName().."TextLeft2") then
1449 TheoryCraft_TooltipData[olddesc]["wandlineleft2"] = getglobal(frame:GetName().."TextLeft2"):GetText()
1450 end
1451 if getglobal(frame:GetName().."TextRight2") and getglobal(frame:GetName().."TextRight2"):IsVisible() then
1452 TheoryCraft_TooltipData[olddesc]["wandlineright2"] = getglobal(frame:GetName().."TextRight2"):GetText()
1453 end
1454 if getglobal(frame:GetName().."TextLeft3") and getglobal(frame:GetName().."TextLeft3"):IsVisible() then
1455 TheoryCraft_TooltipData[olddesc]["wandlineleft3"] = getglobal(frame:GetName().."TextLeft3"):GetText()
1456 end
1457 if getglobal(frame:GetName().."TextRight3") and getglobal(frame:GetName().."TextRight3"):IsVisible() then
1458 TheoryCraft_TooltipData[olddesc]["wandlineright3"] = getglobal(frame:GetName().."TextRight3"):GetText()
1459 end
1460 if getglobal(frame:GetName().."TextLeft4") then
1461 if getglobal(frame:GetName().."TextLeft4"):GetText() ~= olddesc then
1462 TheoryCraft_TooltipData[olddesc]["wandlineleft4"] = getglobal(frame:GetName().."TextLeft4"):GetText()
1463 end
1464 end
1465 else
1466 if getglobal(frame:GetName().."TextLeft3") then
1467 if (getglobal(frame:GetName().."TextLeft3"):GetText()) then
1468 if (getglobal(frame:GetName().."TextLeft3"):GetText() ~= olddesc) and (strfind(getglobal(frame:GetName().."TextLeft3"):GetText(), (TheoryCraft_Locale.CooldownRem) or "Cooldown remaining: ") == nil) then
1469 TheoryCraft_TooltipData[olddesc]["basecasttime"] = getglobal(frame:GetName().."TextLeft3"):GetText()
1470 end
1471 end
1472 end
1473 if getglobal(frame:GetName().."TextRight2") and getglobal(frame:GetName().."TextRight2"):IsVisible() then
1474 TheoryCraft_TooltipData[olddesc]["spellrange"] = getglobal(frame:GetName().."TextRight2"):GetText()
1475 end
1476 if getglobal(frame:GetName().."TextRight3") and getglobal(frame:GetName().."TextRight3"):IsVisible() then
1477 TheoryCraft_TooltipData[olddesc]["cooldown"] = getglobal(frame:GetName().."TextRight3"):GetText()
1478 if (i.overcooldown) and (TheoryCraft_TooltipData[olddesc]["averagedam"]) then
1479 if (strfind(TheoryCraft_TooltipData[olddesc]["cooldown"], "%d+.%d+"..TheoryCraft_Locale.Cooldown)) then
1480 TheoryCraft_TooltipData[olddesc]["dps"] = TheoryCraft_TooltipData[olddesc]["averagedam"]/tonumber(findpattern(TheoryCraft_TooltipData[olddesc]["cooldown"], "%d+.%d+"))
1481 elseif (strfind(TheoryCraft_TooltipData[olddesc]["cooldown"], "%d+"..TheoryCraft_Locale.Cooldown)) then
1482 TheoryCraft_TooltipData[olddesc]["dps"] = TheoryCraft_TooltipData[olddesc]["averagedam"]/tonumber(findpattern(TheoryCraft_TooltipData[olddesc]["cooldown"], "%d+"))
1483 end
1484 end
1485 end
1486 end
1487 TheoryCraft_TooltipData[olddesc]["spellname"] = spellname
1488 TheoryCraft_TooltipData[olddesc]["spellrank"] = spellrank
1489 TheoryCraft_TooltipData[olddesc]["spellnumber"] = i2
1490 TheoryCraft_TooltipData[olddesc]["dontdpsafterresists"] = i.dontdpsafterresists
1491 TheoryCraft_TooltipData[olddesc]["isheal"] = i.isheal
1492 TheoryCraft_TooltipData[olddesc]["iscombo"] = i.iscombo
1493 TheoryCraft_TooltipData[olddesc]["cancrit"] = i.cancrit
1494 TheoryCraft_TooltipData[olddesc]["shoot"] = i.shoot
1495 TheoryCraft_TooltipData[olddesc]["ismelee"] = i.ismelee
1496 TheoryCraft_TooltipData[olddesc]["isranged"] = i.isranged
1497 TheoryCraft_TooltipData[olddesc]["autoshot"] = i.autoshot
1498 TheoryCraft_TooltipData[olddesc]["armor"] = i.armor
1499 TheoryCraft_TooltipData[olddesc]["binary"] = i.binary
1500 TheoryCraft_TooltipData[olddesc]["dodps"] = i.dodps
1501 TheoryCraft_TooltipData[olddesc]["isseal"] = i.isseal
1502 TheoryCraft_TooltipData[olddesc]["drain"] = i.drain
1503 TheoryCraft_TooltipData[olddesc]["holynova"] = i.holynova
1504 TheoryCraft_TooltipData[olddesc]["dontdomax"] = i.dontdomax
1505 TheoryCraft_TooltipData[olddesc]["overcd"] = i.overcooldown
1506 if (TheoryCraft_Settings["GenerateList"] == "") or (string.find(TheoryCraft_Settings["GenerateList"], string.gsub(spellname, "-", "%%-").."%("..spellrank.."%)")) then
1507 TheoryCraft_TooltipData[olddesc]["showonbutton"] = true
1508 end
1509 if TheoryCraft_Data["reporttimes"] then
1510 TheoryCraft_Data["buttonsgenerated"] = TheoryCraft_Data["buttonsgenerated"]+1
1511 TheoryCraft_Data["timetaken"] = TheoryCraft_Data["timetaken"]+GetTime()-timer
1512 end
1513 end
1514  
1515 local data2 = {}
1516  
1517 local function UpdateTarget(data)
1518 if data == nil then return end
1519 data["resistscore"] = 0
1520 if data["basemanacost"] and data["manacost"] then
1521 if UnitMana("player") >= data["basemanacost"] then
1522 data["spellcasts"] = 1+math.floor((UnitMana("player")-(data["basemanacost"] or data["manacost"]))/data["manacost"])
1523 if data["dpm"] and data["maxoomdam"] then
1524 data["maxoomdamremaining"] = data["dpm"]*data["manacost"]*data["spellcasts"]
1525 end
1526 if data["hpm"] and data["maxoomheal"] then
1527 data["maxoomhealremaining"] = data["hpm"]*data["manacost"]*data["spellcasts"]
1528 end
1529 else
1530 data["spellcasts"] = 0
1531 if data["maxoomdam"] then
1532 data["maxoomdamremaining"] = 0
1533 end
1534 if data["maxoomheal"] then
1535 data["maxoomdamremaining"] = 0
1536 end
1537 end
1538 end
1539  
1540 if data.iscombo then
1541 if data["description"] == nil then return end
1542 local points = GetComboPoints()
1543 data["mindamage"] = data["combo"..points.."mindamage"] or 0
1544 data["maxdamage"] = data["combo"..points.."maxdamage"] or 0
1545 if (data["comboconvert"]) and (points > 0) then
1546 local add = (UnitMana("player")-35)*data["comboconvert"]
1547 data["mindamage"] = data["mindamage"]+add
1548 data["maxdamage"] = data["maxdamage"]+add
1549 end
1550 data["critdmgmin"] = data["mindamage"]*(data["critbonus"]+1)
1551 data["critdmgmax"] = data["maxdamage"]*(data["critbonus"]+1)
1552 data["averagedamnocrit"] = (data["maxdamage"]+data["mindamage"])/2
1553 data["averagecritdam"] = data["averagedamnocrit"]*data["critbonus"]
1554 data["averagedam"] = data["averagedamnocrit"]+data["averagecritdam"]*(data["critdmgchance"] or 0)/100
1555 data["description"] = data["beforecombo"]
1556 local search = TheoryCraft_MeleeComboReader
1557 search = string.gsub(search, "%(%%d%+%)", points, 1)
1558 local replace = TheoryCraft_MeleeComboReplaceWith
1559 replace = "%*"..string.gsub(replace, "%$points%$", points).."%*"
1560 data["description"] = string.gsub(data["description"], search, replace)
1561 end
1562 if data["isheal"] then return end
1563 if data["armor"] and TheoryCraft_Settings["mitigation"] then
1564 TheoryCraft_DeleteTable(data2)
1565 TheoryCraft_CopyTable(data, data2)
1566 data = data2
1567  
1568 local armormult = TheoryCraft_Data.armormultinternal
1569 if data["description"] then
1570 if data["mindamage"] then
1571 data["description"] = string.gsub(data["description"], round(data["mindamage"]), round(data["mindamage"]*armormult))
1572 end
1573 if data["maxdamage"] then
1574 data["description"] = string.gsub(data["description"], round(data["maxdamage"]), round(data["maxdamage"]*armormult))
1575 end
1576 end
1577  
1578 if data["mindamage"] then data["mindamage"] = data["mindamage"]*armormult end
1579 if data["maxdamage"] then data["maxdamage"] = data["maxdamage"]*armormult end
1580 if data["critdmgmin"] then data["critdmgmin"] = data["critdmgmin"]*armormult end
1581 if data["critdmgmax"] then data["critdmgmax"] = data["critdmgmax"]*armormult end
1582 if data["nextstrdam"] then data["nextstrdam"] = data["nextstrdam"]*armormult end
1583 if data["nextagidam"] then data["nextagidam"] = data["nextagidam"]*armormult end
1584 if data["nexthitdam"] then data["nexthitdam"] = data["nexthitdam"]*armormult end
1585 if data["nextcritdam"] then data["nextcritdam"] = data["nextcritdam"]*armormult end
1586 if data["dpm"] then data["dpm"] = data["dpm"]*armormult end
1587 if data["dps"] then data["dps"] = data["dps"]*armormult end
1588 if data["averagedam"] then data["averagedam"] = data["averagedam"]*armormult end
1589 if data["averagedamnocrit"] then data["averagedamnocrit"] = data["averagedamnocrit"]*armormult end
1590 if data["maxoomdam"] then data["maxoomdam"] = data["maxoomdam"]*armormult end
1591 if data["maxoomdamremaining"] then data["maxoomdamremaining"] = data["maxoomdamremaining"]*armormult end
1592 if data["maxoomdamfloored"] then data["maxoomdamfloored"] = data["maxoomdamfloored"]*armormult end
1593  
1594  
1595 if data["asrotationdps"] then data["asrotationdps"] = data["asrotationdps"]*armormult end
1596 if data["msrotationdps"] then data["asrotationdps"] = data["asrotationdps"]*armormult end
1597 if data["arcrotationdps"] then data["arcrotationdps"] = (data["arcrotationdps"] - (data["arcmagicdps"] or 0))*armormult + (data["arcmagicdps"] or 0) end
1598  
1599 return data
1600 end
1601 if data["ismelee"] then return end
1602 if data["isseal"] then return end
1603 if data["autoshot"] then return end
1604  
1605 local penamount = 0
1606 if data["schools"] then
1607 for k, v in pairs(data["schools"]) do
1608 penamount = penamount + TheoryCraft_GetStat(v.."penetration")
1609 for k, v2 in pairs(TheoryCraft_PrimarySchools) do
1610 if (type(v2) == "table") and (v2.name == v) and (TheoryCraft_Settings["resistscores"][v2.name]) then
1611 if TheoryCraft_Settings["resistscores"][v2.name] == "~" then
1612 data["resistscore"] = data["resistscore"]+1000
1613 else
1614 data["resistscore"] = data["resistscore"]+TheoryCraft_Settings["resistscores"][v2.name]
1615 end
1616 end
1617 end
1618 end
1619 end
1620 if data["resistscore"] > 0 then
1621 if data["resistscore"] < penamount then
1622 data["resistscore"] = 0
1623 else
1624 data["resistscore"] = data["resistscore"]-penamount
1625 end
1626 end
1627 penamount = data["resistscore"]
1628 if penamount < 0 then
1629 penamount = 0
1630 end
1631  
1632 data["resistscore"] = data["resistscore"]/(UnitLevel("player")*20/3)
1633 if (data["resistscore"] > 0.75) and (data["resistscore"] < 2.5) then
1634 data["resistscore"] = 0.75
1635 end
1636  
1637 data["resistlevel"] = UnitLevel("target")
1638 local playerlevel = UnitLevel("player")
1639 if data["resistlevel"] == -1 then
1640 data["resistlevel"] = 63
1641 end
1642 if data["resistlevel"] == 0 then
1643 data["resistlevel"] = playerlevel
1644 end
1645 data["resistrate"] = data["resistlevel"]-playerlevel
1646 if UnitIsPlayer("target") then
1647 if (data["resistrate"] < -2) then
1648 data["resistrate"] = 1
1649 elseif (data["resistrate"] == -2) then
1650 data["resistrate"] = 2
1651 elseif (data["resistrate"] == -1) then
1652 data["resistrate"] = 3
1653 elseif (data["resistrate"] == 0) then
1654 data["resistrate"] = 4
1655 elseif (data["resistrate"] == 1) then
1656 data["resistrate"] = 5
1657 elseif (data["resistrate"] == 2) then
1658 data["resistrate"] = 6
1659 elseif (data["resistrate"] > 2) then
1660 data["resistrate"] = 13+(data["resistrate"]-3)*7
1661 end
1662 else
1663 if (data["resistrate"] < -2) then
1664 data["resistrate"] = 1
1665 elseif (data["resistrate"] == -2) then
1666 data["resistrate"] = 2
1667 elseif (data["resistrate"] == -1) then
1668 data["resistrate"] = 3
1669 elseif (data["resistrate"] == 0) then
1670 data["resistrate"] = 4
1671 elseif (data["resistrate"] == 1) then
1672 data["resistrate"] = 5
1673 elseif (data["resistrate"] == 2) then
1674 data["resistrate"] = 6
1675 elseif (data["resistrate"] > 2) then
1676 data["resistrate"] = 17+(data["resistrate"]-3)*11
1677 end
1678 end
1679 if (data["resistrate"] > 99) then
1680 data["resistrate"] = 99
1681 end
1682 data["resistrate"] = data["resistrate"]+(data["hitbonus"] or 0)
1683 local toomuchhit
1684 if (data["resistrate"] < 2) then
1685 toomuchhit = 1
1686 data["resistrate"] = 1
1687 end
1688 local damworth
1689 if (data["nexthitdam"]) and (not data["dontdpsafterresists"]) then
1690  
1691 local misschance = data["resistrate"]
1692  
1693 local critchance = (data["critchance"] or 0)
1694 if (misschance + critchance) > 100 then
1695 critchance = 100-misschance
1696 end
1697 local hitchance = 100-critchance-misschance
1698  
1699 local averagehitdam = (data["averagedamnocrit"] or 0)*(data["manamultiplier"] or 1)
1700 local averagecritdam = ((data["averagedamnocrit"] or 0)*(data["manamultiplier"] or 1)+(data["averagecritdam"] or 0))
1701 if TheoryCraft_Settings["dontcrit"] then
1702 hitchance = hitchance + critchance
1703 critchance = 0
1704 end
1705 hitchance = hitchance/100*averagehitdam
1706 critchance = critchance/100*averagecritdam
1707 data["dpsafterresists"] = round((hitchance+critchance)/data["casttime"], 1)
1708 end
1709  
1710 if not TheoryCraft_Settings["dontresist"] then
1711 return
1712 end
1713 TheoryCraft_DeleteTable(data2)
1714 TheoryCraft_CopyTable(data, data2)
1715 data = data2
1716  
1717 local resistmult = (1-data["resistscore"])
1718 if data["binary"] then
1719 if resistmult > 1 then
1720 resistmult = 1
1721 end
1722 end
1723 if resistmult < 0 then
1724 resistmult = 0
1725 penamount = 0
1726 end
1727  
1728 if data["nextcritdam"] then data["nextcritdam"] = data["nextcritdam"] * resistmult end
1729 if data["nexthitdam"] then data["nexthitdam"] = data["nexthitdam"] * resistmult end
1730  
1731 if data["overcd"] == nil then
1732 if data["dps"] and data["dpsafterresists"] then
1733 resistmult = resistmult * data["dpsafterresists"]/data["dps"]
1734 data["dps"] = data["dpsafterresists"]
1735 end
1736 end
1737 if data["binary"] then
1738 data["resistrate"] = data["resistrate"] + data["resistscore"]*100
1739 if data["resistrate"] > 100 then
1740 data["resistrate"] = 100
1741 end
1742 end
1743  
1744 if data["damworth"] then data["damworth"] = data["damworth"] * resistmult end
1745  
1746 if penamount < 10 then
1747 if data["nextpendam"] then
1748 data["nextpendam"] = data["nextpendam"] * (penamount/10)
1749 end
1750 end
1751 data["dontshowupto"] = ""
1752  
1753 if data["nexthitdamequive"] and data["nexthitdam"] and data["damworth"] then data["nexthitdamequive"] = data["nexthitdam"] / data["damworth"] end
1754 if data["nextcritdamequive"] and data["nextcritdam"] and data["damworth"] then data["nextcritdamequive"] = data["nextcritdam"] / data["damworth"] end
1755 if data["nextpendamequive"] and data["nextpendam"] and data["damworth"] then data["nextpendamequive"] = data["nextpendam"] / data["damworth"] end
1756  
1757 if data["damworth"] == 0 then data["nexthitdamequive"] = 0 end
1758 if data["damworth"] == 0 then data["nextcritdamequive"] = 0 end
1759  
1760 if data["dps"] then data["dps"] = data["dps"] * resistmult end
1761 if data["withdotdps"] then data["withdotdps"] = data["withdotdps"] * resistmult end
1762 if data["dpsdam"] then data["dpsdam"] = data["dpsdam"] * resistmult end
1763 if data["averagedam"] then data["averagedam"] = data["averagedam"] * resistmult end
1764 if data["averagedamnocrit"] then data["averagedamnocrit"] = data["averagedamnocrit"] * resistmult end
1765 if data["dpm"] then data["dpm"] = data["dpm"] * resistmult end
1766 if data["withdotdpm"] then data["withdotdpm"] = data["withdotdpm"] * resistmult end
1767 if data["maxoomdam"] then data["maxoomdam"] = data["maxoomdam"] * resistmult end
1768 if data["maxevocoomdam"] then data["maxevocoomdam"] = data["maxevocoomdam"] * resistmult end
1769 if toomuchhit then data["nexthitdam"] = 0 data["nexthitdamequive"] = "At max, 0.00" end
1770 if penamount == 0 then data["nextpendamequive"] = "At max, 0.00" end
1771 return data
1772 end
1773  
1774 function TheoryCraft_GetSpellDataByFrame(frame, force)
1775 if frame == nil then return nil end
1776 if frame:NumLines() == 0 then return nil end
1777 if getglobal(frame:GetName().."TextLeft"..frame:NumLines()) == nil then return nil end
1778 local desc = getglobal(frame:GetName().."TextLeft"..frame:NumLines()):GetText()
1779 if (frame:NumLines() == 1) and (desc ~= "Attack") then
1780 local pos = strfind(desc, "%(%d+%)")
1781 if not pos then return nil end
1782 local data = TheoryCraft_GetSpellDataByName(string.sub(desc, 1, pos-1), tonumber(string.sub(desc, pos+1, string.len(desc)-1)), force, true)
1783 if data == nil then return nil end
1784 if data.spellnumber == nil then return nil end
1785 frame:SetSpell(data.spellnumber,BOOKTYPE_SPELL)
1786 return data
1787 end
1788 if TheoryCraft_TooltipData[desc] and TheoryCraft_TooltipData[desc].spellname then
1789 return UpdateTarget(TheoryCraft_TooltipData[desc]) or TheoryCraft_TooltipData[desc]
1790 end
1791 TheoryCraft_GenerateTooltip(frame, nil, nil, nil, true, nil, force)
1792 return UpdateTarget(TheoryCraft_TooltipData[desc]) or TheoryCraft_TooltipData[desc]
1793 end
1794  
1795 function TheoryCraft_GetSpellDataByName(spellname, spellrank, force, macro)
1796 if spellrank == nil then spellrank = 0 end
1797 local description = TheoryCraft_TooltipData[spellname.."("..spellrank..")"] or (macro and TheoryCraft_TooltipData[spellname.."MACRO("..spellrank..")"])
1798 if (description) then
1799 if TheoryCraft_TooltipData[description] and TheoryCraft_TooltipData[description].spellname then
1800 return UpdateTarget(TheoryCraft_TooltipData[description]) or TheoryCraft_TooltipData[description]
1801 end
1802 end
1803 TheoryCraft_GenerateTooltip(nil, spellname, spellrank, nil, true, macro)
1804 if TheoryCraft_TooltipData[TheoryCraft_TooltipData[spellname.."("..spellrank..")"]] and TheoryCraft_TooltipData[TheoryCraft_TooltipData[spellname.."("..spellrank..")"]].spellname then
1805 return UpdateTarget(TheoryCraft_TooltipData[TheoryCraft_TooltipData[spellname.."("..spellrank..")"]]) or TheoryCraft_TooltipData[TheoryCraft_TooltipData[spellname.."("..spellrank..")"]]
1806 elseif TheoryCraft_TooltipData[TheoryCraft_TooltipData[spellname.."MACRO("..spellrank..")"]] and TheoryCraft_TooltipData[TheoryCraft_TooltipData[spellname.."MACRO("..spellrank..")"]].spellname then
1807 return UpdateTarget(TheoryCraft_TooltipData[TheoryCraft_TooltipData[spellname.."MACRO("..spellrank..")"]]) or TheoryCraft_TooltipData[TheoryCraft_TooltipData[spellname.."MACRO("..spellrank..")"]]
1808 end
1809 end
1810  
1811 function TheoryCraft_GetSpellDataByDescription(description, force)
1812 if TheoryCraft_TooltipData[description] and TheoryCraft_TooltipData[description].spellname then
1813 return UpdateTarget(TheoryCraft_TooltipData[description]) or TheoryCraft_TooltipData[description]
1814 end
1815 if (force ~= true) and (TheoryCraft_Settings["GenerateList"] ~= "") then
1816 return
1817 end
1818 local i = 1
1819 local spellname, spellrank
1820 local testdesc
1821 while (true) do
1822 spellname, spellrank = GetSpellName(i,BOOKTYPE_SPELL)
1823 if spellname == nil then break end
1824 spellrank = tonumber(findpattern(spellrank, "%d+"))
1825 if spellrank == nil then spellrank = 0 end
1826 TCTooltip:SetOwner(UIParent,"ANCHOR_NONE")
1827 TCTooltip:SetSpell(i,BOOKTYPE_SPELL)
1828 testdesc = getglobal("TCTooltipTextLeft"..TCTooltip:NumLines()):GetText()
1829 if testdesc == description then
1830 TheoryCraft_GenerateTooltip(TCTooltip, spellname, spellrank, i, true)
1831 return UpdateTarget(TheoryCraft_TooltipData[description]) or TheoryCraft_TooltipData[description]
1832 end
1833 i = i + 1
1834 end
1835 end
1836  
1837 function TheoryCraft_GenerateAll()
1838 TheoryCraft_DeleteTable(TheoryCraft_TooltipData)
1839 TheoryCraft_DeleteTable(TheoryCraft_UpdatedButtons)
1840 if TheoryCraft_UpdateOutfitTab then TheoryCraft_UpdateOutfitTab() end
1841 end