vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1  
2 --[[
3  
4 CombatStats3 - Stat Damage Tracking
5 AUTHOR: DmgInc on most forums / Glacier on official WoW forums
6 THANKS TO: The dude(ette) who made DPSPlus for showing me the light on how to parse the combat log
7 The dude(ette) who made Clock for the time conversion routines
8  
9 Rev. 3.3 - ReEnabled the option to only show the stats on a mouseclick
10 2.16.05 - DPS caluculated is now 15 seconds w/no option to change
11 - Added end of fight stats option to turn on/off
12 - Slash commands will save between sessions when not using w/cosmos
13  
14 Rev. 3.2 - Added end of fight statistics
15 2.09.05 - Using PLAYER_REGEN_DISABLED ENABLED to tell when you
16 are in/out of combat for end of fight info
17  
18 Rev. 3.1 - Lots of fixes to track pet stats
19 2.07.05
20  
21 Rev. 3.0 - Initial version to track Defensive DPS
22 12.xx.04
23  
24 Rev 2.03 - Now really really works w/o cosmos
25 11.15.04
26  
27 Rev 2.02 - Now works w/o cosmos
28 11.14.04 - Changed the text display frame
29 - Fixed the crit % running out of the frame when it was 100%
30 - Put "Default" attack at top of the list
31 - Added in a "Total", put it at the bottom of the list
32 - UI is now movalbe
33 - UI will update itself while you are attacking if it is visible
34 - Fixed a bug where the close "X" button couldn't be pressed
35 - Now uses OnEvent and OnUpdate
36 - Pet damage is now tracked
37 - DOT damage totals are correctly shown
38 - Hopefully got rid of bogus entries
39  
40  
41 Rev 2.01 - First release w/new UI
42 11.05.04
43  
44 ]]
45  
46 if ( CT_AddMovable ) then
47 CT_AddMovable("CombatStatsFrame", "CombatStats", "TOPLEFT", "TOPLEFT", "UIParent", 150, 0, function(status) end);
48 end
49  
50  
51  
52 --
53 -- Cosmos Cofig variables
54 --
55  
56 CombatStats_Config = { };
57 CombatStats_Config.CombatStats_OnOff = 1;
58 CombatStats_Config.CombatStats_HideOnNoTarget = 0;
59 CombatStats_Config.CombatStats_EndOfFight = 0;
60 CombatStats_Config.CombatStats_UseMouseOver = 0;
61  
62 CombatStats_LastUpdate = 0;
63 CombatStats_UpdateFreq = 0.1;
64 CombatStats_DPSLen = 15; -- Calculate DPS over the last 60 seconds
65  
66 defcritCount = 0;
67 speccritCount= 0;
68  
69 timestamps = {};
70 takenTimestamps = {};
71  
72 players = {};
73 playersTaken = {};
74  
75 dmg = {};
76 dmgTaken = {};
77  
78 dpstotals = {};
79 dpsTakenTotals = {};
80  
81 defCrits = {0};
82 specCrits = {0};
83  
84 defCritTotals = {};
85 specCritTotals = {};
86  
87 bInCombat = 0;
88 bHasDefault = 0;
89  
90 totalDamage = 0;
91  
92 --
93 -- Last fight info
94 --
95  
96 lastFightStart = 0;
97 lastFightFinish = 0;
98 lastFightPlayerDamage = 0;
99 lastFightPetDamage = 0;
100  
101 mobDied = 0;
102 regenEnabled = 0;
103 leaveCombat = 0;
104  
105 overallCombatTime = 0;
106  
107 overallSwings = 0;
108 overallMisses = 0;
109 overallDodged = 0;
110 overallParried = 0;
111 overallEvaded = 0;
112 overallBlocked = 0;
113 overallResisted = 0;
114 overallImmuned = 0;
115 overallDeflected = 0;
116 overallHits = 0;
117 overallNonCrits = 0;
118 overallCrits = 0;
119 overallmaxCrit = 0;
120 overallminCrit = 0;
121 overallmaxReg = 0;
122 overallminReg = 0;
123 overallRegDmg = 0;
124 overallCritDmg = 0;
125 overallLastcrit = 0;
126  
127  
128 attackNames = {};
129 specialAttacks = {};
130 specialAttackLog = {};
131  
132 totalHits = 0;
133 totalCrits = 0;
134 specialsCount = 0;
135 combatTime = 1;
136  
137 CombatStats_Old_TargetFrame_OnShow = nil;
138 CombatStats_Old_TargetFrame_OnHide = nil;
139  
140 CombatStats_ChatCommandHandlers={};
141  
142 bFirstTime = 1;
143  
144 CombatStatsVars = { };
145 CombatStatsSessionVars = { };
146 DeathCount = 0;
147 DeathLog = { };
148 CombatStatsRecentVars = { };
149 CombatStatsByName = { };
150 CombatStatsSessionByName = { };
151 CombatStatsDisplay = { };
152  
153 function CombatStats_ChatCommandHandler(msg)
154 msg = string.lower(msg);
155 local firsti, lasti, command, setStr = string.find (msg, "(%w+) ([%w%.]+)");
156 if ((not command) and msg) then
157 command = msg;
158 end
159 if (command) then
160 for curCommand in CombatStats_ChatCommandHandlers do
161 if (command == curCommand) then
162 if (setStr) then
163 CombatStats_ChatCommandHandlers[curCommand](setStr);
164 else
165 CombatStats_ChatCommandHandlers[curCommand]();
166 end
167 return;
168 end
169 end
170 end
171 Print("All slash command can start with either /cs or /combatstats example: /cs enable or /combatstats enable");
172 Print("Then you can pass on or off to them, or pass a number for ones that need a number ex.");
173 Print("/cs enable on");
174 Print("/cs enable off");
175 Print("");
176 Print("enable [on | off] - 'Enable/disabwle CombatStats, on or off'");
177 Print("target [on | off] - 'Only show DPS meter when you have a target'");
178 Print("mouseover [on | off] - 'Show detailed window on mouseover'");
179 Print("endoffight [on | off] - 'Show end of fight information'");
180 Print("reset yes - 'Rest all stats to 0'");
181  
182 end
183  
184 --
185 -- Slash command handler
186 --
187  
188 function CombatStats_Enable_ChatCommandHandler(msg)
189  
190 if (msg) then
191 msg = string.upper(msg);
192 -- Toggle appropriately
193 if (string.find(msg, "ON")) then
194 CombatStats_Config.CombatStats_OnOff = 1;
195 elseif (string.find(msg, "OFF")) then
196 CombatStats_Config.CombatStats_OnOff = 0;
197 end
198 end
199  
200 if(Cosmos_RegisterConfiguration ~= nil) then
201 Cosmos_UpdateValue("COMBATSTATS_CONFIG_ONOFF", CSM_CHECKONOFF, CombatStats_Config.CombatStats_OnOff);
202 end
203  
204 CombatStats_UpdateVisibility();
205  
206 end
207 CombatStats_ChatCommandHandlers["enable"] = CombatStats_Enable_ChatCommandHandler;
208  
209 function CombatStats_Target_ChatCommandHandler(msg)
210  
211 if (msg) then
212 msg = string.upper(msg);
213 -- Toggle appropriately
214 if (string.find(msg, "ON")) then
215 CombatStats_Config.CombatStats_HideOnNoTarget = 1;
216 elseif (string.find(msg, "OFF")) then
217 CombatStats_Config.CombatStats_HideOnNoTarget = 0;
218 end
219 end
220  
221 if(Cosmos_RegisterConfiguration ~= nil) then
222 Cosmos_UpdateValue("COMBATSTATS_CONFIG_HIDEONNOTARGET", CSM_CHECKONOFF, CombatStats_Config.CombatStats_HideOnNoTarget);
223 end
224  
225 CombatStats_UpdateVisibility();
226  
227 end
228 CombatStats_ChatCommandHandlers["target"] = CombatStats_Target_ChatCommandHandler;
229  
230 function CombatStats_Mouseover_ChatCommandHandler(msg)
231  
232 if (msg) then
233 msg = string.upper(msg);
234 -- Toggle appropriately
235 if (string.find(msg, "ON")) then
236 CombatStats_Config.CombatStats_UseMouseOver = 1;
237 elseif (string.find(msg, "OFF")) then
238 CombatStats_Config.CombatStats_UseMouseOver = 0;
239 end
240 end
241  
242 if(Cosmos_RegisterConfiguration ~= nil) then
243 Cosmos_UpdateValue("COMBATSTATS_CONFIG_USEMOUSEOVER", CSM_CHECKONOFF, CombatStats_Config.CombatStats_UseMouseOver);
244 end
245  
246 CombatStats_UpdateVisibility();
247  
248 end
249 CombatStats_ChatCommandHandlers["mouseover"] = CombatStats_Target_ChatCommandHandler;
250  
251 function CombatStats_Endoffight_ChatCommandHandler(msg)
252  
253 if (msg) then
254 msg = string.upper(msg);
255 -- Toggle appropriately
256 if (string.find(msg, "ON")) then
257 CombatStats_Config.CombatStats_EndOfFight = 1;
258 elseif (string.find(msg, "OFF")) then
259 CombatStats_Config.CombatStats_EndOfFight = 0;
260 end
261 end
262  
263 if(Cosmos_RegisterConfiguration ~= nil) then
264 Cosmos_UpdateValue("COMBATSTATS_CONFIG_ENDOFFIGHT", CSM_CHECKONOFF, CombatStats_Config.CombatStats_EndOfFight);
265 end
266  
267 CombatStats_UpdateVisibility();
268  
269 end
270 CombatStats_ChatCommandHandlers["endoffight"] = CombatStats_Target_ChatCommandHandler;
271  
272 function CombatStats_Reset_ChatCommandHandler(msg)
273  
274 if (msg) then
275 msg = string.upper(msg);
276 -- Toggle appropriately
277 if (string.find(msg, "YES")) then
278 CombatStats_Reset();
279 end
280 end
281  
282 end
283 CombatStats_ChatCommandHandlers["reset"] = CombatStats_Reset_ChatCommandHandler;
284  
285 --
286 -- Cosmos Config Handlers
287 --
288  
289 function CombatStats_HideOnNoTarget_OnOff(toggle)
290 CombatStats_Config.CombatStats_HideOnNoTarget = toggle;
291 CombatStats_UpdateVisibility();
292 end
293  
294 function CombatStats_Watch_OnOff(toggle)
295 CombatStats_Config.CombatStats_OnOff = toggle;
296 CombatStats_UpdateVisibility();
297 end
298  
299 function CombatStats_UseMouseOver_OnOff(toggle)
300 CombatStats_Config.CombatStats_UseMouseOver = toggle;
301 CombatStats_UpdateVisibility();
302 end
303  
304 function CombatStats_EndOfFight_OnOff(toggle)
305 CombatStats_Config.CombatStats_EndOfFight = toggle;
306 CombatStats_UpdateVisibility();
307 end
308  
309  
310 function CombatStats_UpdateVisibility(hasTarget)
311 if (not hasTarget) then
312 if (TargetFrame:IsVisible()) then
313 hasTarget = 1;
314 else
315 hasTarget = 0;
316 end
317 end
318 if (CombatStats_Config.CombatStats_OnOff == 1) then
319 if (CombatStats_Config.CombatStats_HideOnNoTarget == 1) then
320 if (hasTarget == 1) then
321 CombatStatsFrame:Show();
322 else
323 CombatStatsFrame:Hide();
324 end
325 else
326 CombatStatsFrame:Show();
327 end
328  
329 --
330 -- Register the events to watch
331 --
332  
333  
334 else
335 CombatStatsFrame:Hide();
336 end
337 end
338  
339 function CombatStats_Reset()
340  
341 defcritCount = 0;
342 speccritCount= 0;
343 timestamps = {};
344 players = {};
345 dmg = {};
346 dpstotals = {};
347 defCrits = {0};
348 specCrits = {0};
349 defCritTotals = {};
350 specCritTotals = {};
351  
352 totalDamage = 0;
353  
354 attackNames = {};
355 specialAttacks = {};
356 specialAttackLog = {};
357  
358 totalHits = 0;
359 totalCrits = 0;
360 specialsCount = 0;
361 bHasDefault = 0;
362  
363 overallSwings = 0;
364 overallMisses = 0;
365 overallDodged = 0;
366 overallParried = 0;
367 overallEvaded = 0;
368 overallBlocked = 0;
369 overallResisted = 0;
370 overallImmuned = 0;
371 overallDeflected = 0;
372 overallHits = 0;
373 overallNonCrits = 0;
374 overallCrits = 0;
375 overallmaxCrit = 0;
376 overallminCrit = 0;
377 overallmaxReg = 0;
378 overallminReg = 0;
379 overallRegDmg = 0;
380 overallCritDmg = 0;
381 overallLastcrit = 0;
382  
383 CombatStatsText:SetText("Overall DPS :: ");
384  
385 CombatStatsGeneralNameTextLabel:SetText("N/A");
386  
387 CombatStatsNonCritHitsStatText:SetText("0");
388 CombatStatsNonCritDamageStatText:SetText("0");
389 CombatStatsNonCritMinMaxStatText:SetText("0 / 0");
390 CombatStatsNonCritAvgStatText:SetText("0.0");
391 CombatStatsNonCritPercentDamageStatText:SetText("0.0 %");
392  
393 CombatStatsCritHitsStatText:SetText("0");
394 CombatStatsCritDamageStatText:SetText("0");
395 CombatStatsCritMinMaxStatText:SetText("0 / 0");
396 CombatStatsCritAvgStatText:SetText("0.0");
397 CombatStatsCritPercentDamageStatText:SetText("0.0 %");
398  
399 CombatStatsGeneralTotalHitsHits:SetText("0");
400 CombatStatsGeneralSwingsLabel:SetText("0");
401  
402 CombatStatsGeneralMissesTextLabel:SetText("0");
403 CombatStatsGeneralMissesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
404  
405 CombatStatsGeneralDodgesTextLabel:SetText("0");
406 CombatStatsGeneralDodgesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
407  
408 CombatStatsGeneralParriedTextLabel:SetText("0");
409 CombatStatsGeneralParriedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
410  
411 CombatStatsGeneralBlockedTextLabel:SetText("0");
412 CombatStatsGeneralBlockedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
413  
414 CombatStatsGeneralResistedTextLabel:SetText("0");
415 CombatStatsGeneralResistedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
416  
417 CombatStatsGeneralImmunedTextLabel:SetText("0");
418 CombatStatsGeneralImmunedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
419  
420 CombatStatsGeneralEvadedTextLabel:SetText("0");
421 CombatStatsGeneralEvadedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
422  
423 CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
424  
425 CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE.."N/A");
426  
427 CombatStatsOverallCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
428  
429 CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."0.0 %");
430 CombatStatsAttackCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
431  
432 UIDropDownMenu_SetText(CS_DROPDOWN_SELECT_TEXT,CombatStatsAttackDropDown);
433  
434  
435 end
436  
437  
438 function CombatStatDPSLen(checked,value)
439 CombatStats_DPSLen = value;
440 end
441  
442 -- Register w/ Cosmos Config and set up a chat watch
443 function CombatStats_RegisterCosmos()
444 if( (Cosmos_RegisterConfiguration ~= nil)) then
445 Cosmos_RegisterConfiguration(
446 "COS_COMBATSTATS",
447 "SECTION",
448 COMBATSTATS_CONFIG_HEADER,
449 COMBATSTATS_CONFIG_HEADER_INFO
450 );
451 Cosmos_RegisterConfiguration(
452 "COS_COMBATSTATS_HEADER",
453 "SEPARATOR",
454 COMBATSTATS_CONFIG_HEADER,
455 COMBATSTATS_CONFIG_HEADER_INFO
456 );
457 Cosmos_RegisterConfiguration(
458 "COS_COMBATSTATS_ONOFF",
459 "CHECKBOX",
460 COMBATSTATS_CONFIG_ONOFF,
461 COMBATSTATS_CONFIG_ONOFF_INFO,
462 CombatStats_Watch_OnOff,
463 CombatStats_Config.CombatStats_OnOff
464 );
465 Cosmos_RegisterConfiguration(
466 "COS_COMBATSTATS_USEMOUSEOVER_ONOFF",
467 "CHECKBOX",
468 COMBATSTATS_CONFIG_USEMOUSEOVER,
469 COMBATSTATS_CONFIG_USEMOUSEOVER_INFO,
470 CombatStats_UseMouseOver_OnOff,
471 CombatStats_Config.CombatStats_UseMouseOver,
472  
473 );
474 Cosmos_RegisterConfiguration(
475 "COS_COMBATSTATS_HIDEONNOTARGET_ONOFF",
476 "CHECKBOX",
477 COMBATSTATS_CONFIG_HIDEONNOTARGET,
478 COMBATSTATS_CONFIG_HIDEONNOTARGET_INFO,
479 CombatStats_HideOnNoTarget_OnOff,
480 CombatStats_Config.CombatStats_HideOnNoTarget
481 );
482 Cosmos_RegisterConfiguration(
483 "COS_COMBATSTATS_ENDOFFIGHT_ONOFF",
484 "CHECKBOX",
485 COMBATSTATS_CONFIG_ENDOFFIGHT,
486 COMBATSTATS_CONFIG_ENDOFFIGHT_INFO,
487 CombatStats_EndOfFight_OnOff,
488 CombatStats_Config.CombatStats_EndOfFight
489 );
490  
491  
492 Cosmos_RegisterChatCommand (
493 "COMBATSTATS_COMMANDS",
494 {"/cs", "/combatsats"},
495 CombatStats_ChatCommandHandler,
496 CS_CHAT_COMMAND_INFO
497 );
498 end
499  
500 end
501  
502 function ShowLastFightDPS()
503  
504 --
505 -- Show the last fight DPS
506 --
507  
508 local totalFightTime
509 local playerDPS
510 local petDPS
511 local petPct
512 local playerText = "%.1f sec.\nTotal Damage : %d\nOverall Fight DPS : %.1f\n";
513 local petText = "Your pet did %d or %.1f%% of your overall damage.\nPet DPS : %.1f";
514 local text = "Fight Statistics\nDuration : ";
515  
516  
517 if( (bInCombat == 0) and (lastFightFinish > lastFightStart)) then
518  
519 totalFightTime = lastFightFinish - lastFightStart;
520 petDPS = lastFightPetDamage / totalFightTime;
521 playerDPS = lastFightPlayerDamage / totalFightTime;
522  
523 if(lastFightPetDamge ~=0) then
524 petPct = (lastFightPetDamage / lastFightPlayerDamage) * 100;
525 end
526  
527 text = text ..format(playerText, totalFightTime,lastFightPlayerDamage,playerDPS);
528  
529 if(lastFightPetDamage ~= 0) then
530 text = text ..format(petText,lastFightPetDamage,petPct,petDPS);
531 end
532  
533 if(DEFAULT_CHAT_FRAME) then
534  
535 DEFAULT_CHAT_FRAME:AddMessage(text);
536  
537 end
538  
539 end
540  
541  
542 end
543  
544 function CombatStats_OnEvent()
545  
546 --
547 -- Don't do all this unless
548 -- combat stats is turned on
549 --
550  
551 if ( not CombatStats_Config.CombatStats_OnOff ) then
552 return;
553 end
554  
555  
556 if (event == "PLAYER_REGEN_ENABLED") then
557 regenEnabled = GetTime();
558 if( (lastFightPlayerDamage > 0) and (bInCombat == 1) ) then
559 lastFightFinish = GetTime();
560 bInCombat = 0;
561 if(CombatStats_Config.CombatStats_EndOfFight == 1) then
562 ShowLastFightDPS();
563 end
564 end
565  
566 end
567  
568 -- if (event == "PLAYER_LEAVE_COMBAT") then
569 -- leaveCombat = GetTime();
570 -- if( (lastFightPlayerDamage > 0) and (bInCombat == 1) ) then
571 -- lastFightFinish = GetTime();
572 -- bInCombat = 0;
573 -- if(CombatStats_Config.CombatStats_EndOfFight == 1) then
574 -- ShowLastFightDPS();
575 -- end
576 -- end
577 -- end
578  
579 if (event == "PLAYER_REGEN_DISABLED") then
580 if (bInCombat == 0) then
581 lastFightStart = GetTime();
582 bInCombat = 1;
583 lastFightPlayerDamage = 0;
584 lastFightPetDamage = 0;
585 end
586 end
587  
588 local p, d;
589 local curtime = combatTime;
590  
591 if( event == "CHAT_MSG_COMBAT_SELF_HITS"
592 or event == "CHAT_MSG_COMBAT_SELF_MISSES"
593 or event == "CHAT_MSG_SPELL_SELF_DAMAGE"
594 or event == "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE"
595 or event == "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE"
596 ) then
597  
598 for creatureName, damage,damageType, spell in string.gfind(arg1, "(.+) suffers (%d+) (.+) damage from your (.+).") do
599 CombatStats_AddSpecialData(spell,"dot",damage,curtime);
600 CombatStats_AddDPSEntry("Your", damage);
601 return;
602 end
603  
604 for spell, creatureName, damage in string.gfind(arg1, "Your (.+) hits (.+) for (%d+).") do
605 CombatStats_AddSpecialData(spell,"hit",damage,curtime);
606 CombatStats_AddDPSEntry("Your", damage);
607 return;
608 end
609  
610 for creatureName, damage in string.gfind(arg1, "You hit (.+) for (%d+)") do
611 CombatStats_AddSpecialData("Default","hit",damage,curtime);
612 CombatStats_AddDPSEntry("Your", damage);
613 return;
614 end
615 for spell, creatureName, damage in string.gfind(arg1, "Your (.+) crits (.+) for (%d+).") do
616 CombatStats_AddSpecialData(spell,"crit",damage,curtime);
617 CombatStats_AddDPSEntry("Your", damage);
618 return;
619 end
620 for creatureName, damage in string.gfind(arg1, "You crit (.+) for (%d+)") do
621 CombatStats_AddSpecialData("Default","crit",damage,curtime);
622 CombatStats_AddDPSEntry("Your", damage);
623 return;
624 end
625 for creatureName in string.gfind(arg1, "You miss (.+).") do
626 CombatStats_AddSpecialData("Default","miss",0,curtime);
627 return;
628 end
629 for creatureName in string.gfind(arg1, "You attack. (.+) parries.") do
630 CombatStats_AddSpecialData("Default","parry",0,curtime);
631 return;
632 end
633 for creatureName in string.gfind(arg1, "You attack. (.+) evades.") do
634 CombatStats_AddSpecialData("Default","evade",0,curtime);
635 return;
636 end
637 for creatureName in string.gfind(arg1, "You attack. (.+) dodges.") do
638 CombatStats_AddSpecialData("Default","dodge",0,curtime);
639 return;
640 end
641 for creatureName in string.gfind(arg1, "You attack. (.+) deflects.") do
642 CombatStats_AddSpecialData("Default","deflect",0,curtime);
643 return;
644 end
645 for creatureName in string.gfind(arg1, "You attack. (.+) blocks.") do
646 CombatStats_AddSpecialData("Default","block",0,curtime);
647 return;
648 end
649 for spell, creatureName in string.gfind(arg1, "Your (.+) was blocked by (.+).") do
650 CombatStats_AddSpecialData(spell,"block",0,curtime);
651 return;
652 end
653 for spell, creatureName in string.gfind(arg1, "Your (.+) was deflected by (.+).") do
654 CombatStats_AddSpecialData(spell,"deflect",0,curtime);
655 return;
656 end
657 for spell, creatureName in string.gfind(arg1, "Your (.+) was dodged by (.+).") do
658 CombatStats_AddSpecialData(spell,"dodge",0,curtime);
659 return;
660 end
661 for spell, creatureName in string.gfind(arg1, "Your (.+) was evaded by (.+).") do
662 CombatStats_AddSpecialData(spell,"evade",0,curtime);
663 return;
664 end
665 for spell, creatureName in string.gfind(arg1, "Your (.+) is parried by (.+)") do
666 CombatStats_AddSpecialData(spell,"parry",0,curtime);
667 return;
668 end
669 for spell, creatureName in string.gfind(arg1, "Your (.+) was resisted by (.+).") do
670 CombatStats_AddSpecialData(spell,"resist",0,curtime);
671 return;
672 end
673 for spell, creatureName in string.gfind(arg1, "Your (.+) failed. (.+) is immune.") do
674 CombatStats_AddSpecialData(spell,"immune",0,curtime);
675 return;
676 end
677 for spell, creatureName in string.gfind(arg1, "Your (.+) missed (.+).") do
678 CombatStats_AddSpecialData(spell,"miss",0,curtime);
679 return;
680 end
681  
682 end
683  
684 if( event == "CHAT_MSG_COMBAT_PET_HITS" ) then
685  
686 bInCombat = 1;
687  
688 for petName, creatureName, damage in string.gfind(arg1, "(.+) crits (.+) for (%d+).") do
689 CombatStats_AddSpecialData("[Pet] Default","crit",damage,curtime);
690 CombatStats_AddDPSEntry("Your", damage);
691 return;
692 end
693  
694 for petName, creatureName, damage in string.gfind(arg1, "(.+) hits (.+) for (%d+).") do
695 CombatStats_AddSpecialData("[Pet] Default","hit",damage,curtime);
696 CombatStats_AddDPSEntry("Your", damage);
697 return;
698 end
699 end
700  
701 if (event == "CHAT_MSG_SPELL_PET_DAMAGE") then
702  
703 for petName, spell, creatureName, damage in string.gfind(arg1, "(.+)'s (.+) hits (.+) for (%d+).") do
704 if (petName == UnitName('pet') or petName == 'your pet') then
705 CombatStats_AddSpecialData("[Pet] "..spell,"hit",damage,curtime);
706 CombatStats_AddDPSEntry("Your", damage);
707 end
708 return;
709 end
710  
711 for petName, spell, creatureName, damage in string.gfind(arg1, "(.+)'s (.+) crits (.+) for (%d+).") do
712 if (petName == UnitName('pet') or petName == 'your pet') then
713 CombatStats_AddSpecialData("[Pet] "..spell,"crit",damage,curtime);
714 CombatStats_AddDPSEntry("Your", damage);
715 end
716 return;
717 end
718  
719 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was blocked by (.*).") do
720 if (petName == UnitName('pet') or petName == 'your pet') then
721 CombatStats_AddSpecialData("[Pet] "..spell,"block",0,curtime);
722 end
723 return;
724 end
725  
726 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was dodged by (.*).") do
727 if (petName == UnitName('pet') or petName == 'your pet') then
728 CombatStats_AddSpecialData("[Pet] "..spell,"dodge",0,curtime);
729 end
730 return;
731 end
732  
733 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was evaded by (.*).") do
734 if (petName == UnitName('pet') or petName == 'your pet') then
735 CombatStats_AddSpecialData("[Pet] "..spell,"evade",0,curtime);
736 end
737 return;
738 end
739  
740 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) fails. (.+) is immune.") do
741 if (petName == UnitName('pet') or petName == 'your pet') then
742 CombatStats_AddSpecialData("[Pet] "..spell,"immune",0,curtime);
743 end
744 return;
745 end
746  
747 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was resisted by (.*).") do
748 if (petName == UnitName('pet') or petName == 'your pet') then
749 CombatStats_AddSpecialData("[Pet] "..spell,"resist",0,curtime);
750 end
751 return;
752 end
753  
754 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) misses (.*).") do
755 if (petName == UnitName('pet') or petName == 'your pet') then
756 CombatStats_AddSpecialData("[Pet] "..spell,"miss",0,curtime);
757 end
758 return;
759 end
760  
761 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) missed (.*).") do
762 if (petName == UnitName('pet') or petName == 'your pet') then
763 CombatStats_AddSpecialData("[Pet] "..spell,"miss",0,curtime);
764 end
765 return;
766 end
767  
768 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) failed. (.+) is immune.") do
769 if (petName == UnitName('pet') or petName == 'your pet') then
770 CombatStats_AddSpecialData("[Pet] "..spell,"immune",0,curtime);
771 end
772 return;
773 end
774 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) missed (.+).") do
775 if (petName == UnitName('pet') or petName == 'your pet') then
776 CombatStats_AddSpecialData("[Pet] "..spell,"miss",0,curtime);
777 end
778 return;
779 end
780 for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was deflected by (.+).") do
781 if (petName == UnitName('pet') or petName == 'your pet') then
782 CombatStats_AddSpecialData("[Pet] "..spell,"deflect",0,curtime);
783 end
784 return;
785 end
786  
787 end
788  
789 if (event == "CHAT_MSG_COMBAT_PET_MISSES") then
790  
791 bInCombat = 1;
792  
793 for petName, creatureName in string.gfind(arg1, "(.+) misses (.*).") do
794 if (petName == UnitName('pet') or petName == 'your pet') then
795 CombatStats_AddSpecialData("[Pet] Default","miss",0,curtime);
796 end
797 return;
798 end
799  
800 for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) parries.") do
801 if (petName == UnitName('pet') or petName == 'your pet') then
802 CombatStats_AddSpecialData("[Pet] Default","parry",0,curtime);
803 end
804 return;
805 end
806 for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) evades.") do
807 if (petName == UnitName('pet') or petName == 'your pet') then
808 CombatStats_AddSpecialData("[Pet] Default","evade",0,curtime);
809 end
810 return;
811 end
812 for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) dodges.") do
813 if (petName == UnitName('pet') or petName == 'your pet') then
814 CombatStats_AddSpecialData("[Pet] Default","dodge",0,curtime);
815 end
816 return;
817 end
818 for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) deflects.") do
819 if (petName == UnitName('pet') or petName == 'your pet') then
820 CombatStats_AddSpecialData("[Pet] Default","deflect",0,curtime);
821 end
822 return;
823 end
824 for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) blocks.") do
825 if (petName == UnitName('pet') or petName == 'your pet') then
826 CombatStats_AddSpecialData("[Pet] Default","block",0,curtime);
827 end
828 return;
829 end
830  
831  
832 end
833  
834 if(event == "CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS") then
835  
836 bInCombat = 1;
837  
838 for creatureName, damage,tmpStr in string.gfind(arg1, "(.+) hits you for (%d+). (.+) blocked") do
839 CombatStats_AddDefDPSEntry("Your",damage);
840 CombatStats_AddSpecialData("Defensive","hit",damage,curtime);
841 CombatStats_AddSpecialData("Defensive","block",0,curtime);
842 return;
843 end
844 for creatureName, damage in string.gfind(arg1, "(.+) hits you for (%d+)") do
845 CombatStats_AddDefDPSEntry("Your",damage);
846 CombatStats_AddSpecialData("Defensive","hit",damage,curtime);
847 return;
848 end
849 for creatureName, damage in string.gfind(arg1, "(.+) crits you for (%d+).") do
850 CombatStats_AddDefDPSEntry("Your",damage);
851 CombatStats_AddSpecialData("Defensive","crit",damage,curtime);
852 return;
853 end
854  
855 end
856  
857 if( event == "CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE") then
858  
859  
860 for creatureName, spell, damage in string.gfind(arg1, "(.+)'s (.+) hits you for (%d+).") do
861 CombatStats_AddDefDPSEntry("Your",damage);
862 CombatStats_AddSpecialData("Defensive","hit",damage,curtime);
863 return;
864 end
865  
866 for creatureName, spell, damage in string.gfind(arg1, "(.+)'s (.+) crits you for (%d+).") do
867 CombatStats_AddDefDPSEntry("Your",damage);
868 CombatStats_AddSpecialData("Defensive","crit",damage,curtime);
869 return;
870 end
871  
872 for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was blocked%.") do
873 CombatStats_AddSpecialData("Defensive","block",0,curtime);
874 return;
875 end
876 for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was deflected%.") do
877 CombatStats_AddSpecialData("Defensive","deflect",0,curtime);
878 return;
879 end
880 for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was dodged%.") do
881 CombatStats_AddSpecialData("Defensive","dodge",0,curtime);
882 return;
883 end
884 for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was evaded%.") do
885 CombatStats_AddSpecialData("Defensive","evade",0,curtime);
886 return;
887 end
888 for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) failed. You are immune.") do
889 CombatStats_AddSpecialData("Defensive","immune",0,curtime);
890 return;
891 end
892 for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) misses you.") do
893 CombatStats_AddSpecialData("Defensive","miss",0,curtime);
894 return;
895 end
896 for creatureName, spell in string.gfind(arg1, "You parry (.+)'s (.+)") do
897 CombatStats_AddSpecialData("Defensive","parry",0,curtime);
898 return;
899 end
900 for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was resisted%.") do
901 CombatStats_AddSpecialData("Defensive","resist",0,curtime);
902 return;
903 end
904 end
905 if (event == "CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES") then
906  
907  
908 for creatureName in string.gfind(arg1, "(.+) misses you.") do
909 CombatStats_AddSpecialData("Defensive","miss",0,curtime);
910 return;
911 end
912 for creatureName in string.gfind(arg1, "(.+) attacks. You parry.") do
913 CombatStats_AddSpecialData("Defensive","parry",0,curtime);
914 return;
915 end
916 for creatureName in string.gfind(arg1, "(.+) attacks. You evade.") do
917 CombatStats_AddSpecialData("Defensive","evade",0,curtime);
918 return;
919 end
920 for creatureName in string.gfind(arg1, "(.+) attacks. You dodge.") do
921 CombatStats_AddSpecialData("Defensive","dodge",0,curtime);
922 return;
923 end
924 for creatureName in string.gfind(arg1, "(.+) attacks. You deflect.") do
925 CombatStats_AddSpecialData("Defensive","deflect",0,curtime);
926 return;
927 end
928 for creatureName in string.gfind(arg1, "(.+) attacks. You block.") do
929 CombatStats_AddSpecialData("Defensive","block",0,curtime);
930 return;
931 end
932 end
933  
934 if ( event == "CHAT_MSG_SPELL_SELF_BUFF" or event == "CHAT_MSG_SPELL_PARTY_BUFF" or event == "CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF" ) then
935 local useless, useless, spell, amount = string.find(arg1, "Your (.+) critically heals .+ for (%d+)%.");
936 if ( spell and amount ) then
937 CombatStats_AddSpecialData("[Heal] Total","crit",amount,curtime, 1);
938 CombatStats_AddSpecialData("[Heal] "..spell,"crit",amount,curtime, 1);
939 elseif ( string.find(arg1, "Your (.+) heals .+ for (%d+)%.") ) then
940 local useless, useless, spell, amount = string.find(arg1, "Your (.+) heals .+ for (%d+)%.");
941 if ( spell and amount ) then
942 CombatStats_AddSpecialData("[Heal] Total","hit",amount,curtime, 1);
943 CombatStats_AddSpecialData("[Heal] "..spell,"hit",amount,curtime, 1);
944 end
945 end
946 end
947  
948 if ( event == "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS" or event == "CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS" ) then
949 local useless, useless, amount, spell = string.find(arg1, ".+ gains (%d+) health from your (.+)%.");
950 if ( spell and amount ) then
951 CombatStats_AddSpecialData("[Heal] Total","hit",amount,curtime, 1);
952 CombatStats_AddSpecialData("[Heal] "..spell,"hot",amount,curtime, 1);
953 end
954 end
955 if ( event == "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS" ) then
956 local useless, useless, amount, spell = string.find(arg1, "You gain (%d+) health from (.+)%.");
957 if ( not string.find(arg1, "'s") and spell and amount ) then
958 CombatStats_AddSpecialData("[Heal] Total","hit",amount,curtime, 1);
959 CombatStats_AddSpecialData("[Heal] "..spell,"hot",amount,curtime, 1);
960 end
961 end
962 end
963  
964 --
965 -- Add/Check for attack(s)
966 --
967  
968 function CombatStats_AddSpecialData(specialName,type,dmg,time, heal)
969  
970  
971 --
972 -- If we haven't logged this attack
973 -- Create a record in the table for it
974 --
975  
976 --print2("Adding : "..specialName .." with damage : "..dmg.."at : "..time);
977  
978 if(specialName ~= "Defensive" and not heal ) then
979 lastFightPlayerDamage = lastFightPlayerDamage + dmg;
980 totalDamage = totalDamage + dmg;
981 end
982  
983 for creatureName,tempJunk in string.gfind(specialName, "(.+)Pet(.+)") do
984 -- print2("creatureName : "..creatureName);
985 -- print2("tempJunk : "..tempJunk);
986 -- print2("Adding pet special : "..specialName.. " with damage of : "..dmg);
987 lastFightPetDamage = lastFightPetDamage + dmg;
988 end
989  
990 if (type == "dot") then
991 specialName = specialName .." [DOT]";
992 elseif ( type == "hot" ) then
993 specialName = specialName .." [HOT]";
994 end
995  
996 if(specialName == "Default") then
997 bHasDefault = 1;
998 end
999  
1000 if ( not specialAttacks[specialName] ) then
1001 specialsCount = specialsCount + 1;
1002 table.insert(attackNames,specialName);
1003  
1004 specialAttackLog[specialsCount] = {
1005 index = specialsCount,
1006 name = specialName,
1007 isDOT = 0,
1008 dotDmg = 0,
1009 dotTicks = 0,
1010 totalSwings = 0,
1011 totalMisses = 0,
1012 totalDodged = 0,
1013 totalParried = 0,
1014 totalEvaded = 0,
1015 totalBlocked = 0,
1016 totalResisted = 0,
1017 totalImmuned = 0,
1018 totalDeflected = 0,
1019 totalHits = 0,
1020 totalNonCrits = 0,
1021 totalCrits = 0,
1022 maxCrit = 0,
1023 minCrit = 0,
1024 maxReg = 0,
1025 minReg = 0,
1026 totalRegDmg = 0,
1027 totalCritDmg = 0,
1028 lastCrit = 0,
1029 }
1030  
1031 specialAttacks[specialName] = specialAttackLog[specialsCount];
1032  
1033 local info;
1034  
1035 info = {};
1036 info.text = specialName;
1037 info.func = CombatStatsAttack_OnClick;
1038 UIDropDownMenu_AddButton(info);
1039  
1040 end
1041  
1042 --
1043 -- Now add the data
1044 --
1045  
1046  
1047 if(specialName ~= "Defensive" and not heal ) then
1048 specialAttacks[specialName].totalSwings = specialAttacks[specialName].totalSwings + 1;
1049 overallSwings = overallSwings + 1;
1050  
1051 if(type == "crit") then
1052  
1053 totalHits = totalHits + 1;
1054 totalCrits = totalCrits + 1;
1055 specialAttacks[specialName].totalCrits = specialAttacks[specialName].totalCrits +1;
1056 specialAttacks[specialName].totalCritDmg = specialAttacks[specialName].totalCritDmg + dmg;
1057 specialAttacks[specialName].lastCrit = time;
1058 specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
1059  
1060 overallCrits = overallCrits + 1;
1061 overallCritDmg = overallCritDmg + dmg;
1062 overallLastcrit = time;
1063  
1064 --
1065 -- Set the initial min/max
1066 --
1067  
1068 if(specialAttacks[specialName].maxCrit == 0) then
1069 specialAttacks[specialName].maxCrit = dmg;
1070 end
1071  
1072 if(specialAttacks[specialName].minCrit == 0) then
1073 specialAttacks[specialName].minCrit = dmg;
1074 end
1075  
1076 if(overallmaxCrit == 0) then
1077 overallmaxCrit = dmg;
1078 end
1079  
1080 if(overallminCrit == 0) then
1081 overallminCrit = dmg;
1082 end
1083  
1084 --
1085 -- Check to see if this dmg
1086 -- is a new min or max
1087 --
1088  
1089 if(tonumber(dmg) < tonumber(specialAttacks[specialName].minCrit)) then
1090 specialAttacks[specialName].minCrit = dmg;
1091 end
1092  
1093 if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxCrit)) then
1094 specialAttacks[specialName].maxCrit = dmg;
1095 end
1096  
1097 if(tonumber(dmg) < tonumber(overallminCrit)) then
1098 overallminCrit = dmg;
1099 end
1100  
1101 if(tonumber(dmg) > tonumber(overallmaxCrit)) then
1102 overallmaxCrit = dmg;
1103 end
1104  
1105 end
1106  
1107 if(type == "hit") then
1108  
1109 totalHits = totalHits + 1;
1110 specialAttacks[specialName].isDOT = 0;
1111 specialAttacks[specialName].totalNonCrits = specialAttacks[specialName].totalNonCrits +1;
1112 specialAttacks[specialName].totalRegDmg = specialAttacks[specialName].totalRegDmg + dmg;
1113 specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
1114  
1115 overallNonCrits = overallNonCrits + 1;
1116 overallRegDmg = overallRegDmg + dmg;
1117  
1118 --
1119 -- Set the initial min/max
1120 --
1121  
1122 if(specialAttacks[specialName].maxReg == 0) then
1123 specialAttacks[specialName].maxReg = dmg;
1124 end
1125  
1126 if(specialAttacks[specialName].minReg == 0) then
1127 specialAttacks[specialName].minReg = dmg;
1128 end
1129  
1130 if(overallmaxReg == 0) then
1131 overallmaxReg = dmg;
1132 end
1133  
1134 if(overallminReg == 0) then
1135 overallminReg = dmg;
1136 end
1137  
1138 --
1139 -- Check to see if this dmg
1140 -- is a new min or max
1141 --
1142  
1143 if(tonumber(dmg) < tonumber(specialAttacks[specialName].minReg)) then
1144 specialAttacks[specialName].minReg = dmg;
1145 end
1146  
1147 if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxReg)) then
1148 specialAttacks[specialName].maxReg = dmg;
1149 end
1150  
1151 if(tonumber(dmg) < tonumber(overallminReg)) then
1152 overallminReg = dmg;
1153 end
1154  
1155 if(tonumber(dmg) > tonumber (overallmaxReg)) then
1156 overallmaxReg = dmg;
1157 end
1158  
1159 end
1160  
1161 if(type == "dot") then
1162  
1163 totalHits = totalHits + 1;
1164 specialAttacks[specialName].isDOT = 1;
1165 specialAttacks[specialName].dotTicks = specialAttacks[specialName].dotTicks +1;
1166 specialAttacks[specialName].dotDmg = specialAttacks[specialName].dotDmg + dmg;
1167 specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
1168  
1169 overallNonCrits = overallNonCrits + 1;
1170 overallRegDmg = overallRegDmg + dmg;
1171  
1172 --
1173 -- Set the initial min/max
1174 --
1175  
1176 if(specialAttacks[specialName].maxReg == 0) then
1177 specialAttacks[specialName].maxReg = dmg;
1178 end
1179  
1180 if(specialAttacks[specialName].minReg == 0) then
1181 specialAttacks[specialName].minReg = dmg;
1182 end
1183  
1184 if(overallmaxReg == 0) then
1185 overallmaxReg = dmg;
1186 end
1187  
1188 if(overallminReg == 0) then
1189 overallminReg = dmg;
1190 end
1191  
1192 --
1193 -- Check to see if this dmg
1194 -- is a new min or max
1195 --
1196  
1197 if(tonumber(dmg) < tonumber(specialAttacks[specialName].minReg)) then
1198 specialAttacks[specialName].minReg = dmg;
1199 end
1200  
1201 if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxReg)) then
1202 specialAttacks[specialName].maxReg = dmg;
1203 end
1204  
1205 if(tonumber(dmg) < tonumber(overallminReg)) then
1206 overallminReg = dmg;
1207 end
1208  
1209 if(tonumber(dmg) > tonumber (overallmaxReg)) then
1210 overallmaxReg = dmg;
1211 end
1212  
1213 end
1214  
1215 if(type == "miss") then
1216  
1217 specialAttacks[specialName].totalMisses = specialAttacks[specialName].totalMisses + 1;
1218 overallMisses = overallMisses +1;
1219  
1220 end
1221  
1222 if(type == "dodge") then
1223  
1224 specialAttacks[specialName].totalDodged = specialAttacks[specialName].totalDodged + 1;
1225 overallDodged = overallDodged + 1;
1226  
1227 end
1228  
1229 if(type == "parry") then
1230  
1231 specialAttacks[specialName].totalParried = specialAttacks[specialName].totalParried + 1;
1232 overallParried = overallParried + 1;
1233  
1234 end
1235  
1236 if(type == "block") then
1237  
1238 specialAttacks[specialName].totalBlocked = specialAttacks[specialName].totalBlocked + 1;
1239 overallBlocked = overallBlocked + 1;
1240  
1241 end
1242  
1243 if(type == "evade") then
1244  
1245 specialAttacks[specialName].totalEvaded = specialAttacks[specialName].totalEvaded + 1;
1246 overallEvaded = overallEvaded + 1;
1247  
1248 end
1249  
1250 if(type == "resist") then
1251  
1252 specialAttacks[specialName].totalResisted = specialAttacks[specialName].totalResisted + 1;
1253 overallResisted = overallResisted + 1;
1254  
1255 end
1256  
1257 if(type == "immune") then
1258  
1259 specialAttacks[specialName].totalImmuned = specialAttacks[specialName].totalImmuned + 1;
1260 overallImmuned = overallImmuned + 1;
1261  
1262 end
1263  
1264 if(type == "deflect") then
1265  
1266 specialAttacks[specialName].totalDeflected = specialAttacks[specialName].totalDeflected + 1;
1267 overallDeflected = overallDeflected + 1;
1268  
1269 end
1270  
1271 else
1272  
1273 --
1274 -- Defesnsive info
1275 -- Don't add to overall stats and overa
1276 --
1277  
1278 specialAttacks[specialName].totalSwings = specialAttacks[specialName].totalSwings + 1;
1279  
1280 if(type == "crit") then
1281  
1282 specialAttacks[specialName].totalCrits = specialAttacks[specialName].totalCrits +1;
1283 specialAttacks[specialName].totalCritDmg = specialAttacks[specialName].totalCritDmg + dmg;
1284 specialAttacks[specialName].lastCrit = time;
1285 specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
1286  
1287 --
1288 -- Set the initial min/max
1289 --
1290  
1291 if(specialAttacks[specialName].maxCrit == 0) then
1292 specialAttacks[specialName].maxCrit = dmg;
1293 end
1294  
1295 if(specialAttacks[specialName].minCrit == 0) then
1296 specialAttacks[specialName].minCrit = dmg;
1297 end
1298  
1299 --
1300 -- Check to see if this dmg
1301 -- is a new min or max
1302 --
1303  
1304 if(tonumber(dmg) < tonumber(specialAttacks[specialName].minCrit)) then
1305 specialAttacks[specialName].minCrit = dmg;
1306 end
1307  
1308 if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxCrit)) then
1309 specialAttacks[specialName].maxCrit = dmg;
1310 end
1311  
1312 end
1313  
1314 if(type == "hit") then
1315  
1316 specialAttacks[specialName].isDOT = 0;
1317 specialAttacks[specialName].totalNonCrits = specialAttacks[specialName].totalNonCrits +1;
1318 specialAttacks[specialName].totalRegDmg = specialAttacks[specialName].totalRegDmg + dmg;
1319 specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
1320  
1321 --
1322 -- Set the initial min/max
1323 --
1324  
1325 if(specialAttacks[specialName].maxReg == 0) then
1326 specialAttacks[specialName].maxReg = dmg;
1327 end
1328  
1329 if(specialAttacks[specialName].minReg == 0) then
1330 specialAttacks[specialName].minReg = dmg;
1331 end
1332  
1333 --
1334 -- Check to see if this dmg
1335 -- is a new min or max
1336 --
1337  
1338 if(tonumber(dmg) < tonumber(specialAttacks[specialName].minReg)) then
1339 specialAttacks[specialName].minReg = dmg;
1340 end
1341  
1342 if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxReg)) then
1343 specialAttacks[specialName].maxReg = dmg;
1344 end
1345  
1346 end
1347  
1348 if(type == "hot") then
1349 specialAttacks[specialName].isDOT = 2;
1350 specialAttacks[specialName].dotTicks = specialAttacks[specialName].dotTicks +1;
1351 specialAttacks[specialName].dotDmg = specialAttacks[specialName].dotDmg + dmg;
1352 specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
1353  
1354 --
1355 -- Set the initial min/max
1356 --
1357  
1358 if(specialAttacks[specialName].maxReg == 0) then
1359 specialAttacks[specialName].maxReg = dmg;
1360 end
1361  
1362 if(specialAttacks[specialName].minReg == 0) then
1363 specialAttacks[specialName].minReg = dmg;
1364 end
1365  
1366  
1367 --
1368 -- Check to see if this dmg
1369 -- is a new min or max
1370 --
1371  
1372 if(tonumber(dmg) < tonumber(specialAttacks[specialName].minReg)) then
1373 specialAttacks[specialName].minReg = dmg;
1374 end
1375  
1376 if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxReg)) then
1377 specialAttacks[specialName].maxReg = dmg;
1378 end
1379  
1380 end
1381  
1382 if(type == "miss") then
1383 specialAttacks[specialName].totalMisses = specialAttacks[specialName].totalMisses + 1;
1384 end
1385  
1386 if(type == "dodge") then
1387 specialAttacks[specialName].totalDodged = specialAttacks[specialName].totalDodged + 1;
1388 end
1389  
1390 if(type == "parry") then
1391 specialAttacks[specialName].totalParried = specialAttacks[specialName].totalParried + 1;
1392 end
1393  
1394 if(type == "block") then
1395 specialAttacks[specialName].totalBlocked = specialAttacks[specialName].totalBlocked + 1;
1396 end
1397  
1398 if(type == "evade") then
1399 specialAttacks[specialName].totalEvaded = specialAttacks[specialName].totalEvaded + 1;
1400 end
1401  
1402 if(type == "resist") then
1403 specialAttacks[specialName].totalResisted = specialAttacks[specialName].totalResisted + 1;
1404 end
1405  
1406 if(type == "immune") then
1407 specialAttacks[specialName].totalImmuned = specialAttacks[specialName].totalImmuned + 1;
1408 end
1409  
1410 if(type == "deflect") then
1411 specialAttacks[specialName].totalDeflected = specialAttacks[specialName].totalDeflected + 1;
1412 end
1413  
1414 end
1415 if ( CombatStatsDataFrame.currAttack and CombatStatsDataFrame.currAttack == specialName ) then
1416 CombatStats_UpdateDetails(specialName);
1417 end
1418  
1419 end
1420  
1421 -- CombatStats Event Watcher
1422 --
1423 -- Update Handler
1424 --
1425  
1426  
1427 function CombatStats_OnUpdate(elapsed)
1428 local curtime = GetTime();
1429 local oldesttime = 0;
1430 local oldesttimeTaken = 0;
1431 local deleteindex = 0;
1432 local deleteindexTaken = 0;
1433 local playerFrame;
1434 if ( bInCombat == 1 ) then
1435 combatTime = combatTime + elapsed;
1436 end
1437 --print2("In Combat == " ..bInCombat);
1438  
1439  
1440  
1441  
1442 if (bInCombat == 1) then
1443  
1444 -- Check to see if its time to update the on screen DPS and only update if there are dps entries to save CPU
1445 if ( ((curtime - CombatStats_LastUpdate) > CombatStats_UpdateFreq) and (table.getn(timestamps) > 0) ) then
1446  
1447 -- TODO: Change this to a high to low loop so we can do our subtracts and deletes in the same run
1448  
1449 --
1450 -- Offensive
1451 --
1452  
1453 for k,v in pairs(timestamps) do
1454  
1455 -- Get rid of old dps entries and adjust the totals
1456 if ( (curtime - CombatStats_DPSLen) > v ) then
1457  
1458 -- Subtract this entry from the totals
1459 dpstotals[players[k]] = dpstotals[players[k]] - dmg[k];
1460  
1461 -- Mark for later removal *We can't do the remove here cause table.remove reindexes the list and bones our loop
1462 deleteindex = k;
1463 else
1464 -- were into the good stuff now, stop
1465 oldesttime = v;
1466 break;
1467 end
1468 end
1469  
1470  
1471 -- Remove entries from deleteindex down so we don't miss em
1472 while (deleteindex > 0) do
1473 table.remove(timestamps, deleteindex);
1474 table.remove(players, deleteindex);
1475 table.remove(dmg, deleteindex);
1476 deleteindex = deleteindex -1;
1477 end
1478  
1479 end
1480  
1481 if ( ((curtime - CombatStats_LastUpdate) > CombatStats_UpdateFreq) and (table.getn(takenTimestamps) > 0) ) then
1482  
1483 --
1484 -- Defensive
1485 --
1486  
1487 for w,y in pairs(takenTimestamps) do
1488  
1489 -- Get rid of old dps entries and adjust the totals
1490 if ( (curtime - CombatStats_DPSLen) > y ) then
1491  
1492 -- Subtract this entry from the totals
1493 dpsTakenTotals[playersTaken[w]] = dpsTakenTotals[playersTaken[w]] - dmgTaken[w];
1494  
1495 -- Mark for later removal *We can't do the remove here cause table.remove reindexes the list and bones our loop
1496 deleteindexTaken = w;
1497 else
1498 -- were into the good stuff now, stop
1499 oldesttimeTaken = y;
1500 break;
1501 end
1502 end
1503  
1504 -- Remove entries from deleteindex down so we don't miss em
1505 while (deleteindexTaken > 0) do
1506 table.remove(takenTimestamps, deleteindexTaken);
1507 table.remove(playersTaken, deleteindexTaken);
1508 table.remove(dmgTaken, deleteindexTaken);
1509 deleteindexTaken = deleteindexTaken -1;
1510 end
1511  
1512 end
1513  
1514  
1515 -- NOTE: Everyone calcs off the same oldest time, not their own oldest time.
1516 -- This should give more accurate dps on a per group fight basis.
1517  
1518  
1519 if ( ((curtime - CombatStats_LastUpdate) > CombatStats_UpdateFreq) and (table.getn(timestamps) > 0) ) then
1520  
1521 --local text = "CurTime - Oldesettime : %.1f";
1522 --text = format(text,(curtime - oldesttime));
1523 --print2(text);
1524  
1525 -- Update player DPS
1526 if ( dpstotals["Your"] ~= nil ) then
1527 if(dpsTakenTotals["Your"] ~= nil) then
1528 CombatStatsText:SetText( RED_FONT_COLOR_CODE.. format(TEXT(DPS_DISPLAY), (dpsTakenTotals["Your"] / (curtime - oldesttimeTaken) )) ..NORMAL_FONT_COLOR_CODE.. " / " ..GREEN_FONT_COLOR_CODE.. format(TEXT(DPS_DISPLAY), (dpstotals["Your"] / (curtime - oldesttime) )) );
1529 else
1530 CombatStatsText:SetText( RED_FONT_COLOR_CODE.. "0.0" ..NORMAL_FONT_COLOR_CODE.. " / " ..GREEN_FONT_COLOR_CODE.. format(TEXT(DPS_DISPLAY), (dpstotals["Your"] / (curtime - oldesttime) )) );
1531 end
1532  
1533  
1534 end
1535  
1536 CombatStats_LastUpdate = curtime;
1537 end
1538  
1539 --
1540 -- If the data frame is visible
1541 -- update the selected attack "Real time"
1542 --
1543  
1544 if (CombatStatsDataFrame:IsVisible()) then
1545  
1546 if( UIDropDownMenu_GetText(CombatStatsAttackDropDown) ~= CS_DROPDOWN_SELECT_TEXT) then
1547 CombatStats_UpdateDetails( UIDropDownMenu_GetText(CombatStatsAttackDropDown));
1548 end
1549 end
1550  
1551 end
1552 end
1553  
1554  
1555 -- Called from XML
1556 function CombatStats_OnLoad()
1557 if ( Cosmos_RegisterConfiguration ~= nil) then
1558 CombatStats_RegisterCosmos();
1559 HookFunction("TargetFrame_OnShow", "CombatStats_TargetFrame_OnShow", "after");
1560 HookFunction("TargetFrame_OnHide", "CombatStats_TargetFrame_OnHide", "after");
1561 else
1562 -- Standalone (chatwatch)
1563 CombatStats_Old_TargetFrame_OnShow = TargetFrame_OnShow;
1564 CombatStats_Old_TargetFrame_OnHide = TargetFrame_OnHide;
1565 TargetFrame_OnShow = CombatStats_TargetFrame_OnShow;
1566 TargetFrame_OnHide = CombatStats_TargetFrame_OnHide;
1567  
1568 SLASH_CSSLASH1 = "/combatstats";
1569 SLASH_CSSLASH2 = "/cs";
1570 SlashCmdList["CSSLASH"] = CombatStats_ChatCommandHandler;
1571  
1572 end
1573  
1574 if (not Print) then
1575 setglobal("Print", function(msg, r, g, b, frame, id)
1576 if (not r) then r = 1.0; end
1577 if (not g) then g = 1.0; end
1578 if (not b) then b = 1.0; end
1579 if (not frame) then frame = DEFAULT_CHAT_FRAME; end
1580 if (frame) then
1581 if (not id) then
1582 frame:AddMessage(msg,r,g,b);
1583 else
1584 frame:AddMessage(msg,r,g,b,id);
1585 end
1586 end
1587 end);
1588 end
1589  
1590 this:RegisterEvent("CHAT_MSG_COMBAT_SELF_HITS");
1591 this:RegisterEvent("CHAT_MSG_COMBAT_SELF_MISSES");
1592 this:RegisterEvent("CHAT_MSG_COMBAT_PET_HITS");
1593 this:RegisterEvent("CHAT_MSG_COMBAT_PET_MISSES");
1594 this:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE");
1595 this:RegisterEvent("CHAT_MSG_SPELL_PET_DAMAGE");
1596  
1597 this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE");
1598 this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE");
1599 this:RegisterEvent("CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS");
1600 this:RegisterEvent("CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES");
1601 this:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS");
1602 this:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES");
1603  
1604 this:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE");
1605 this:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE");
1606 this:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_BUFF");
1607 this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS");
1608 this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE");
1609  
1610 this:RegisterEvent("CHAT_MSG_SYSTEM");
1611 this:RegisterEvent("PLAYER_REGEN_ENABLED");
1612 this:RegisterEvent("PLAYER_REGEN_DISABLED");
1613 this:RegisterEvent("PLAYER_LEAVE_COMBAT");
1614 this:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN");
1615 this:RegisterEvent("CHAT_MSG_COMBAT_LOG_ENEMY");
1616 this:RegisterEvent("CHAT_MSG_COMBAT_HOSTILE_DEATH");
1617  
1618 -- Heals
1619 this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS");
1620 this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS");
1621 this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS");
1622  
1623 this:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF");
1624 this:RegisterEvent("CHAT_MSG_SPELL_PARTY_BUFF");
1625 this:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF");
1626  
1627 CombatStatsText:SetText("Overall DPS :: ");
1628 CombatStats_UpdateVisibility();
1629 end
1630  
1631 function CombatStatsAttack_OnClick()
1632  
1633 local attackID = this:GetID();
1634  
1635 UIDropDownMenu_SetSelectedID(CombatStatsAttackDropDown, attackID);
1636 --print2("GetID :: ".. UIDropDownMenu_GetSelectedID(CombatStatsAttackDropDown));
1637 local attackName = UIDropDownMenu_GetText(CombatStatsAttackDropDown);
1638 UIDropDownMenu_SetSelectedValue(CombatStatsAttackDropDown, attackName);
1639 --print2("GetValue :: ".. UIDropDownMenu_GetSelectedValue(CombatStatsAttackDropDown));
1640 UIDropDownMenu_SetText(attackName,CombatStatsAttackDropDown);
1641 --this:SetText(CombatStatsDetailTypes[detailID].value);
1642 --this.text = CombatStatsDetailTypes[detailID].value;
1643  
1644 CombatStats_UpdateDetails(attackName);
1645  
1646 end
1647  
1648 function CombatStatsAttackDropDown_OnLoad()
1649 UIDropDownMenu_Initialize(this, CombatStatsAttackDropDown_Initialize);
1650 end
1651  
1652  
1653 function CombatStatsAttackDropDown_Initialize()
1654 CombatStats_LoadAttackNames();
1655 end
1656  
1657 function CombatStats_LoadAttackNames()
1658  
1659 local info;
1660  
1661 if(table.getn(attackNames) ~= 0) then
1662 if(bHasDefault == 1) then
1663 info = {};
1664 info.text = "Default";
1665 info.func = CombatStatsAttack_OnClick;
1666 UIDropDownMenu_AddButton(info);
1667 end
1668 end
1669  
1670 for i=1, table.getn(attackNames), 1 do
1671  
1672 if(attackNames[i] ~= "Default") then
1673 info = {};
1674 info.text = attackNames[i];
1675 info.func = CombatStatsAttack_OnClick;
1676 UIDropDownMenu_AddButton(info);
1677 end
1678  
1679 end
1680  
1681 if(table.getn(attackNames) ~= 0) then
1682 info = {};
1683 info.text = "Total";
1684 info.func = CombatStatsAttack_OnClick;
1685 UIDropDownMenu_AddButton(info);
1686 end
1687  
1688 end
1689  
1690 --
1691 -- Add the damage to the DPS table
1692 --
1693  
1694 function CombatStats_AddDPSEntry(p, d)
1695  
1696  
1697 table.insert(timestamps, GetTime());
1698 table.insert(players, p);
1699 table.insert(dmg, d);
1700  
1701 -- Keep running totals on group members to shorten calculation times
1702 -- We'll subtract off the expired entries during OnUpdate
1703 if (dpstotals[p] == nil) then
1704 -- print2("dpstotals[p] == nil");
1705 dpstotals[p] = d;
1706 else
1707 -- print2("dpstotals[p] == " ..dpstotals[p] );
1708 dpstotals[p] = dpstotals[p] + d;
1709 -- print2("AFTER : dpstotals[p] == " ..dpstotals[p] );
1710 end
1711  
1712 --print2("Total : " ..dpstotals[p]);
1713 end
1714  
1715  
1716 --
1717 -- Add damage taken to the DPS table
1718 --
1719  
1720 function CombatStats_AddDefDPSEntry(p, d)
1721  
1722 --print2("Adding Entry[" .. p .. "] = " .. d); -- debug
1723 table.insert(takenTimestamps, GetTime());
1724 table.insert(playersTaken, p);
1725 table.insert(dmgTaken, d);
1726  
1727 -- Keep running totals on group members to shorten calculation times
1728 -- We'll subtract off the expired entries during OnUpdate
1729 if (dpsTakenTotals[p] == nil) then
1730 -- print2("dpstotals[p] == nil");
1731 dpsTakenTotals[p] = d;
1732 else
1733 -- print2("dpstotals[p] == " ..dpstotals[p] );
1734 dpsTakenTotals[p] = dpsTakenTotals[p] + d;
1735 -- print2("AFTER : dpstotals[p] == " ..dpstotals[p] );
1736 end
1737  
1738 --print2("Total : " ..dpstotals[p]);
1739 end
1740  
1741 -- Show the stats collected
1742  
1743 function CombatStatsText_OnClick()
1744 if (CombatStatsDataFrame:IsVisible()) then
1745 CombatStatsDataFrame:Hide();
1746 else
1747 if (CombatStats_Config.CombatStats_UseMouseOver == 0) then
1748 CombatStatsText_ShowFrame();
1749 end
1750 end
1751 end
1752  
1753 function CombatStatsText_OnEnter()
1754 if (CombatStats_Config.CombatStats_UseMouseOver == 1) then
1755 CombatStatsText_ShowFrame();
1756 end
1757 end
1758  
1759 function CombatStatsText_ShowFrame()
1760  
1761  
1762 if(bFirstTime == 1) then
1763  
1764 --
1765 -- Set all the default values
1766 --
1767  
1768 CombatStatsGeneralNameLabel:SetText(TEXT(CS_FRAME_GEN_ATTACK_NAME));
1769 CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_HITS_TEXT);
1770 CombatStatsGeneralSwingsTextLabel:SetText(CS_FRAME_SWINGS_TEXT);
1771 CombatStatsGeneralMissesLabel:SetText(CS_FRAME_MISSES_TEXT);
1772 CombatStatsGeneralDodgesLabel:SetText(CS_FRAME_DODGES_TEXT);
1773 CombatStatsGeneralParriedLabel:SetText(CS_FRAME_PARRIES_TEXT);
1774 CombatStatsGeneralBlockedLabel:SetText(CS_FRAME_BLOCKS_TEXT);
1775 CombatStatsGeneralResistedLabel:SetText(CS_FRAME_RESISTS_TEXT);
1776 CombatStatsGeneralImmunedLabel:SetText(CS_FRAME_IMMUNE_TEXT);
1777 CombatStatsGeneralEvadedLabel:SetText(CS_FRAME_EVADES_TEXT );
1778 CombatStatsGeneralDeflectedLabel:SetText(CS_FRAME_DEFLECTS_TEXT);
1779 CombatStatsGeneralPercentDmgLabel:SetText(CS_FRAME_PERCENT_OVERALL_TEXT);
1780 CombatStatsGeneralTimeLastCritLabel:SetText(CS_FRAME_TIME_LASTCRIT_TEXT);
1781  
1782 CombatStatsNonCritHitsLabel:SetText(CS_FRAME_TOTAL_TEXT);
1783 CombatStatsNonCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT);
1784 CombatStatsNonCritMinMaxLabel:SetText(CS_FRAME_MINMAX_TEXT);
1785 CombatStatsNonCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT);
1786 CombatStatsNonCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT);
1787  
1788 CombatStatsCritHitsLabel:SetText(CS_FRAME_TOTAL_TEXT);
1789 CombatStatsCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT);
1790 CombatStatsCritMinMaxLabel:SetText(CS_FRAME_MINMAX_TEXT);
1791 CombatStatsCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT);
1792 CombatStatsCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT);
1793  
1794 CombatStatsGeneralNameTextLabel:SetText("N/A");
1795  
1796 CombatStatsNonCritHitsStatText:SetText("0");
1797 CombatStatsNonCritDamageStatText:SetText("0");
1798 CombatStatsNonCritMinMaxStatText:SetText("0 / 0");
1799 CombatStatsNonCritAvgStatText:SetText("0.0");
1800 CombatStatsNonCritPercentDamageStatText:SetText("0.0 %");
1801  
1802 CombatStatsCritHitsStatText:SetText("0");
1803 CombatStatsCritDamageStatText:SetText("0");
1804 CombatStatsCritMinMaxStatText:SetText("0 / 0");
1805 CombatStatsCritAvgStatText:SetText("0.0");
1806 CombatStatsCritPercentDamageStatText:SetText("0.0 %");
1807  
1808 CombatStatsGeneralTotalHitsHits:SetText("0");
1809 CombatStatsGeneralSwingsLabel:SetText("0");
1810  
1811 CombatStatsGeneralMissesTextLabel:SetText("0");
1812 CombatStatsGeneralMissesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1813  
1814 CombatStatsGeneralDodgesTextLabel:SetText("0");
1815 CombatStatsGeneralDodgesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1816  
1817 CombatStatsGeneralParriedTextLabel:SetText("0");
1818 CombatStatsGeneralParriedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1819  
1820 CombatStatsGeneralBlockedTextLabel:SetText("0");
1821 CombatStatsGeneralBlockedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1822  
1823 CombatStatsGeneralResistedTextLabel:SetText("0");
1824 CombatStatsGeneralResistedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1825  
1826 CombatStatsGeneralImmunedTextLabel:SetText("0");
1827 CombatStatsGeneralImmunedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1828  
1829 CombatStatsGeneralEvadedTextLabel:SetText("0");
1830 CombatStatsGeneralEvadedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1831  
1832 CombatStatsGeneralDeflectedTextLabel:SetText("0");
1833 CombatStatsGeneralDeflectedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1834  
1835 CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
1836  
1837 CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE.."N/A");
1838  
1839 CombatStatsOverallCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
1840  
1841 CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."0.0 %");
1842 CombatStatsAttackCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
1843  
1844 UIDropDownMenu_SetText(CS_DROPDOWN_SELECT_TEXT,CombatStatsAttackDropDown);
1845  
1846 bFirstTime = 0;
1847  
1848 end
1849  
1850 if( UIDropDownMenu_GetText(CombatStatsAttackDropDown) ~= CS_DROPDOWN_SELECT_TEXT) then
1851  
1852 CombatStats_UpdateDetails( UIDropDownMenu_GetText(CombatStatsAttackDropDown));
1853  
1854 end
1855  
1856 CombatStatsDataFrame:Show();
1857  
1858 end
1859  
1860 function CS_ToggleGameMenu(clicked)
1861 if ( clicked ) then
1862 if ( OptionsFrame:IsVisible() ) then
1863 OptionsFrameCancel:Click();
1864 end
1865 if ( GameMenuFrame:IsVisible() ) then
1866 PlaySound("igMainMenuQuit");
1867 HideUIPanel(GameMenuFrame);
1868 else
1869 CloseMenus();
1870 CloseAllWindows()
1871 PlaySound("igMainMenuOpen");
1872 ShowUIPanel(GameMenuFrame);
1873 end
1874 return;
1875 end
1876 if ( StaticPopup_EscapePressed() ) then
1877 elseif ( OptionsFrame:IsVisible() ) then
1878 OptionsFrameCancel:Click();
1879 elseif ( GameMenuFrame:IsVisible() ) then
1880 PlaySound("igMainMenuQuit");
1881 HideUIPanel(GameMenuFrame);
1882 elseif ( CloseMenus() ) then
1883 elseif ( SpellStopCasting() ) then
1884 elseif ( SpellStopTargeting() ) then
1885 elseif ( CloseAllWindows() ) then
1886 CombatStatsDataFrame:Hide();
1887 elseif ( ClearTarget() ) then
1888 else
1889 if ( CombatStatsDataFrame:IsVisible() ) then
1890 CombatStatsDataFrame:Hide();
1891 return;
1892 end
1893 PlaySound("igMainMenuOpen");
1894 ShowUIPanel(GameMenuFrame);
1895 end
1896 end
1897  
1898 ToggleGameMenu = CS_ToggleGameMenu;
1899  
1900 function CombatStats_UpdateDetails(attackName)
1901 CombatStatsDataFrame.currAttack = attackName;
1902 if ( strsub(attackName, 0, 6) == "[Heal]" ) then
1903  
1904 CS_TT_NONCRIT_HITSPCT_TEXT = CS_TT_NONCRIT_HITSPCT_TEXT_HEAL;
1905 CS_TT_CRIT_HITSPCT_TEXT = CS_TT_CRIT_HITSPCT_TEXT_HEAL;
1906 CS_TT_OVERALLDMGPCT_TEXT = CS_TT_OVERALLDMGPCT_TEXT_HEAL;
1907 CS_TT_CRIT_DMGPCT_TEXT = CS_TT_CRIT_DMGPCT_TEXT_HEAL;
1908 CS_TT_NONCRIT_DMGPCT_TEXT = CS_TT_NONCRIT_DMGPCT_TEXT_HEAL;
1909  
1910 CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_HITS_TEXT_HEAL);
1911 CombatStatsGeneralPercentDmgLabel:SetText(CS_FRAME_PERCENT_OVERALL_TEXT_HEAL);
1912 CombatStatsNonCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT_HEAL);
1913 CombatStatsNonCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT_HEAL);
1914 CombatStatsNonCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT_HEAL);
1915 CombatStatsCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT_HEAL);
1916 CombatStatsCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT_HEAL);
1917 CombatStatsCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT_HEAL);
1918  
1919 CombatStatsGeneralSwingsTextLabel:Hide();
1920 else
1921 CS_TT_NONCRIT_HITSPCT_TEXT = CS_TT_NONCRIT_HITSPCT_TEXT_NONHEAL;
1922 CS_TT_CRIT_HITSPCT_TEXT = CS_TT_CRIT_HITSPCT_TEXT_NONHEAL;
1923 CS_TT_OVERALLDMGPCT_TEXT = CS_TT_OVERALLDMGPCT_TEXT_NONHEAL;
1924 CS_TT_CRIT_DMGPCT_TEXT = CS_TT_CRIT_DMGPCT_TEXT_NONHEAL;
1925 CS_TT_NONCRIT_DMGPCT_TEXT = CS_TT_NONCRIT_DMGPCT_TEXT_NONHEAL;
1926  
1927 CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_HITS_TEXT);
1928 CombatStatsGeneralPercentDmgLabel:SetText(CS_FRAME_PERCENT_OVERALL_TEXT);
1929 CombatStatsNonCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT);
1930 CombatStatsNonCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT);
1931 CombatStatsNonCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT);
1932 CombatStatsCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT);
1933 CombatStatsCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT);
1934 CombatStatsCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT);
1935  
1936 CombatStatsGeneralSwingsTextLabel:Show();
1937 end
1938  
1939 local x,y,info;
1940  
1941 --
1942 -- Draw the text for the hits/swings
1943 --
1944  
1945 if(attackName ~= "Total") then
1946  
1947 --
1948 -- Calculate % of hits that are crits
1949 --
1950  
1951 if( (totalCrits) ~= 0) then
1952 CombatStatsOverallCritPctLabel:SetText( format(RED_FONT_COLOR_CODE.."%.2f %%", ( totalCrits / totalHits) * 100.0));
1953 end
1954  
1955 CombatStatsGeneralNameTextLabel:SetText(attackName);
1956 CombatStatsGeneralTotalHitsHits:SetText(specialAttacks[attackName].totalHits);
1957 if ( strsub(attackName, 0, 6) ~= "[Heal]" ) then
1958 CombatStatsGeneralSwingsLabel:SetText(specialAttacks[attackName].totalSwings);
1959 CombatStatsGeneralSwingsLabel:Show();
1960 else
1961 CombatStatsGeneralSwingsLabel:Hide();
1962 end
1963  
1964 CombatStatsGeneralMissesTextLabel:SetText(specialAttacks[attackName].totalMisses);
1965  
1966 if(specialAttacks[attackName].totalMisses ~= 0) then
1967 CombatStatsGeneralMissesPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalMisses / (specialAttacks[attackName].totalSwings) * 100)));
1968 else
1969 CombatStatsGeneralMissesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1970 end
1971  
1972 CombatStatsGeneralDodgesTextLabel:SetText(specialAttacks[attackName].totalDodged);
1973  
1974 if(specialAttacks[attackName].totalDodged ~= 0) then
1975 CombatStatsGeneralDodgesPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalDodged / (specialAttacks[attackName].totalSwings) * 100)));
1976 else
1977 CombatStatsGeneralDodgesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1978 end
1979  
1980 CombatStatsGeneralBlockedTextLabel:SetText(specialAttacks[attackName].totalBlocked);
1981  
1982 if(attackName == "Defensive") then
1983  
1984 if(specialAttacks[attackName].totalBlocked ~= 0) then
1985 CombatStatsGeneralBlockedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalBlocked / (specialAttacks[attackName].totalHits) * 100)));
1986 else
1987 CombatStatsGeneralBlockedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1988 end
1989  
1990 else
1991  
1992 if(specialAttacks[attackName].totalBlocked ~= 0) then
1993 CombatStatsGeneralBlockedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalBlocked / (specialAttacks[attackName].totalSwings) * 100)));
1994 else
1995 CombatStatsGeneralBlockedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
1996 end
1997  
1998 end
1999  
2000 CombatStatsGeneralParriedTextLabel:SetText(specialAttacks[attackName].totalParried);
2001  
2002 if(specialAttacks[attackName].totalParried ~= 0) then
2003 CombatStatsGeneralParriedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalParried / (specialAttacks[attackName].totalSwings) * 100)));
2004 else
2005 CombatStatsGeneralParriedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2006 end
2007  
2008 CombatStatsGeneralResistedTextLabel:SetText(specialAttacks[attackName].totalResisted);
2009  
2010 if(specialAttacks[attackName].totalResisted ~= 0) then
2011 CombatStatsGeneralResistedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalResisted / (specialAttacks[attackName].totalSwings) * 100)));
2012 else
2013 CombatStatsGeneralResistedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2014 end
2015  
2016 CombatStatsGeneralImmunedTextLabel:SetText(specialAttacks[attackName].totalImmuned);
2017  
2018 if(specialAttacks[attackName].totalImmuned ~= 0) then
2019 CombatStatsGeneralImmunedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalImmuned / (specialAttacks[attackName].totalSwings) * 100)));
2020 else
2021 CombatStatsGeneralImmunedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2022 end
2023  
2024 CombatStatsGeneralEvadedTextLabel:SetText(specialAttacks[attackName].totalEvaded);
2025  
2026 if(specialAttacks[attackName].totalEvaded ~= 0) then
2027 CombatStatsGeneralEvadedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalEvaded / (specialAttacks[attackName].totalSwings) * 100)));
2028 else
2029 CombatStatsGeneralEvadedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2030 end
2031  
2032 CombatStatsGeneralDeflectedTextLabel:SetText(specialAttacks[attackName].totalDeflected);
2033  
2034 if(specialAttacks[attackName].totalDeflected ~= 0) then
2035 CombatStatsGeneralDeflectedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalDeflected / (specialAttacks[attackName].totalSwings) * 100)));
2036 else
2037 CombatStatsGeneralDeflectedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2038 end
2039  
2040 --
2041 -- Percent of total damage
2042 --
2043  
2044 if(attackName ~= "Defensive") then
2045 if ( attackName == "[Heal] Total" ) then
2046 CombatStatsGeneralPercentDmgPctLabel:SetText("100.0%");
2047 elseif ( strsub(attackName, 0, 6) == "[Heal]" ) then
2048 if ( specialAttacks[attackName].totalHits ~= 0 ) then
2049 CombatStatsGeneralPercentDmgPctLabel:SetText( format("%.2f %%", ((specialAttacks[attackName].totalRegDmg + specialAttacks[attackName].totalCritDmg + specialAttacks[attackName].dotDmg) / (specialAttacks["[Heal] Total"].totalRegDmg + specialAttacks["[Heal] Total"].totalCritDmg + specialAttacks["[Heal] Total"].dotDmg)) * 100) );
2050 else
2051 CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
2052 end
2053 else
2054  
2055 if(specialAttacks[attackName].totalHits ~=0) then
2056 CombatStatsGeneralPercentDmgPctLabel:SetText( format("%.2f %%", ((specialAttacks[attackName].totalRegDmg + specialAttacks[attackName].totalCritDmg + specialAttacks[attackName].dotDmg) / totalDamage) * 100) );
2057 else
2058 CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
2059 end
2060 end
2061 end
2062  
2063 --
2064 -- Time since last crit
2065 --
2066  
2067 local timeNow;
2068 timeNow = combatTime;
2069  
2070 if(specialAttacks[attackName].lastCrit ~= 0) then
2071 CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE ..Clock_FormatTime( (timeNow - specialAttacks[attackName].lastCrit)));
2072 else
2073 CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE.."N/A");
2074 end
2075  
2076 --
2077 -- Attack Crit %
2078 --
2079  
2080 if (specialAttacks[attackName].totalHits ~= 0) and (specialAttacks[attackName].totalCrits ~= 0) then
2081 CombatStatsAttackCritPctLabel:SetText(format(RED_FONT_COLOR_CODE.."%.1f%%", ( (specialAttacks[attackName].totalCrits) / (specialAttacks[attackName].totalHits)) * 100.0 ));
2082 else
2083 CombatStatsAttackCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
2084 end
2085  
2086 --
2087 -- Attack Non Crit %
2088 --
2089  
2090 if (specialAttacks[attackName].totalHits ~= 0) and (specialAttacks[attackName].totalNonCrits ~= 0) then
2091 CombatStatsAttackNonCritPctLabel:SetText( format(GREEN_FONT_COLOR_CODE.."%.1f%%", ( (specialAttacks[attackName].totalNonCrits) / (specialAttacks[attackName].totalHits)) * 100.0 ));
2092 else
2093 CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."0.0 %");
2094 end
2095  
2096 --
2097 -- Non Crit stats
2098 --
2099  
2100 CombatStatsNonCritHitsStatText:SetText(specialAttacks[attackName].totalNonCrits);
2101 CombatStatsNonCritDamageStatText:SetText(specialAttacks[attackName].totalRegDmg);
2102 CombatStatsNonCritMinMaxStatText:SetText(specialAttacks[attackName].minReg .." / "..specialAttacks[attackName].maxReg);
2103  
2104 if( specialAttacks[attackName].totalRegDmg ~= 0) then
2105  
2106 if( (specialAttacks[attackName].totalHits - specialAttacks[attackName].totalCrits) < 0) then
2107 CombatStatsNonCritAvgStatText:SetText(format("%.1f", specialAttacks[attackName].totalRegDmg / (specialAttacks[attackName].totalCrits - specialAttacks[attackName].totalHits ) ));
2108 end
2109  
2110 if( (specialAttacks[attackName].totalHits - specialAttacks[attackName].totalCrits) == 0 ) then
2111 CombatStatsNonCritAvgStatText:SetText(format("%1.f", specialAttacks[attackName].totalRegDmg / (specialAttacks[attackName].totalCrits) ));
2112 end
2113  
2114 if( (specialAttacks[attackName].totalHits - specialAttacks[attackName].totalCrits) > 0 ) then
2115 CombatStatsNonCritAvgStatText:SetText(format("%1.f",specialAttacks[attackName].totalRegDmg / (specialAttacks[attackName].totalHits - specialAttacks[attackName].totalCrits) ));
2116 end
2117  
2118 else
2119 CombatStatsNonCritAvgStatText:SetText("0.0");
2120 end
2121  
2122 if(specialAttacks[attackName].totalNonCrits ~=0) then
2123 CombatStatsNonCritPercentDamageStatText:SetText( format("%.2f %%", ( specialAttacks[attackName].totalRegDmg / (specialAttacks[attackName].totalRegDmg + specialAttacks[attackName].totalCritDmg )) * 100.0));
2124 else
2125 CombatStatsNonCritPercentDamageStatText:SetText("0.0 %");
2126 end
2127  
2128 --
2129 -- Crit stats
2130 --
2131  
2132 CombatStatsCritHitsStatText:SetText(specialAttacks[attackName].totalCrits);
2133 CombatStatsCritDamageStatText:SetText(specialAttacks[attackName].totalCritDmg);
2134 CombatStatsCritMinMaxStatText:SetText(specialAttacks[attackName].minCrit .." / "..specialAttacks[attackName].maxCrit);
2135  
2136 if( specialAttacks[attackName].totalCritDmg ~= 0) then
2137 CombatStatsCritAvgStatText:SetText(format("%1.f", (specialAttacks[attackName].totalCritDmg / specialAttacks[attackName].totalCrits) ));
2138 else
2139 CombatStatsCritAvgStatText:SetText("0.0");
2140 end
2141  
2142 if(specialAttacks[attackName].totalCrits ~=0) then
2143 CombatStatsCritPercentDamageStatText:SetText(format("%.2f %%", (specialAttacks[attackName].totalCritDmg / ( specialAttacks[attackName].totalRegDmg + specialAttacks[attackName].totalCritDmg )) * 100.10 ));
2144 else
2145 CombatStatsCritPercentDamageStatText:SetText("0.0 %");
2146 end
2147  
2148 --
2149 -- Show DOT Stats
2150 --
2151  
2152  
2153  
2154 if (specialAttacks[attackName].isDOT ==1) then
2155  
2156 CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_TICKS_TEXT);
2157 CombatStatsGeneralSwingsTextLabel:SetText("");
2158 CombatStatsGeneralSwingsLabel:SetText("");
2159  
2160 CombatStatsGeneralTotalHitsHits:SetText(specialAttacks[attackName].dotTicks);
2161 CombatStatsNonCritHitsStatText:SetText(specialAttacks[attackName].dotTicks);
2162 CombatStatsNonCritDamageStatText:SetText(specialAttacks[attackName].dotDmg);
2163  
2164 CombatStatsNonCritMinMaxStatText:SetText(specialAttacks[attackName].minReg .." / "..specialAttacks[attackName].maxReg);
2165 CombatStatsNonCritAvgStatText:SetText(format("%.1f", specialAttacks[attackName].dotDmg / specialAttacks[attackName].dotTicks ));
2166 CombatStatsNonCritPercentDamageStatText:SetText("100.0 %");
2167 CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."100.0%");
2168  
2169 --
2170 -- Should never be a 0 tick entry but just in case
2171 --
2172 -- if(specialAttacks[attackNames[y]].dotTicks ~= 0) then
2173 -- text = text.."\n"..format(TEXT(DOT_AVERAGE),(specialAttacks[attackNames[y]].dotDmg / specialAttacks[attackNames[y]].dotTicks));
2174 -- end
2175 elseif ( specialAttacks[attackName].isDOT ==2) then
2176 CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_HOT_TEXT);
2177 CombatStatsGeneralSwingsTextLabel:SetText("");
2178 CombatStatsGeneralSwingsLabel:SetText("");
2179  
2180 CombatStatsGeneralTotalHitsHits:SetText(specialAttacks[attackName].dotTicks);
2181 CombatStatsNonCritHitsStatText:SetText(specialAttacks[attackName].dotTicks);
2182 CombatStatsNonCritDamageStatText:SetText(specialAttacks[attackName].dotDmg);
2183  
2184 CombatStatsNonCritMinMaxStatText:SetText(specialAttacks[attackName].minReg .." / "..specialAttacks[attackName].maxReg);
2185 CombatStatsNonCritAvgStatText:SetText(format("%.1f", specialAttacks[attackName].dotDmg / specialAttacks[attackName].dotTicks ));
2186 CombatStatsNonCritPercentDamageStatText:SetText("100.0 %");
2187 CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."100.0%");
2188 end
2189  
2190  
2191 else
2192  
2193 --
2194 -- Calculate % of hits that are crits
2195 --
2196  
2197 if( (totalCrits) ~= 0) then
2198 CombatStatsOverallCritPctLabel:SetText( format(RED_FONT_COLOR_CODE.."%.2f %%", ( totalCrits / totalHits) * 100.0));
2199 end
2200  
2201 CombatStatsGeneralNameTextLabel:SetText("Total");
2202 CombatStatsGeneralTotalHitsHits:SetText(totalHits);
2203 CombatStatsGeneralSwingsLabel:SetText(overallSwings);
2204  
2205 CombatStatsGeneralMissesTextLabel:SetText(overallMisses);
2206  
2207 if(overallMisses ~= 0) then
2208 CombatStatsGeneralMissesPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallMisses / (overallSwings) * 100)));
2209 else
2210 CombatStatsGeneralMissesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2211 end
2212  
2213 CombatStatsGeneralDodgesTextLabel:SetText(overallDodged);
2214  
2215 if(overallDodged ~= 0) then
2216 CombatStatsGeneralDodgesPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallDodged / (overallSwings) * 100)));
2217 else
2218 CombatStatsGeneralDodgesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2219 end
2220  
2221 CombatStatsGeneralParriedTextLabel:SetText(overallParried);
2222  
2223 if(overallParried ~= 0) then
2224 CombatStatsGeneralParriedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallParried / (overallSwings) * 100)));
2225 else
2226 CombatStatsGeneralParriedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2227 end
2228  
2229 CombatStatsGeneralResistedTextLabel:SetText(overallResisted);
2230  
2231 if(overallResisted ~= 0) then
2232 CombatStatsGeneralResistedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallResisted / (overallSwings) * 100)));
2233 else
2234 CombatStatsGeneralResistedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2235 end
2236  
2237 CombatStatsGeneralImmunedTextLabel:SetText(overallImmuned);
2238  
2239 if(overallImmuned ~= 0) then
2240 CombatStatsGeneralImmunedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallImmuned / (overallSwings) * 100)));
2241 else
2242 CombatStatsGeneralImmunedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2243 end
2244  
2245 CombatStatsGeneralEvadedTextLabel:SetText(overallEvaded);
2246  
2247 if(overallEvaded ~= 0) then
2248 CombatStatsGeneralEvadedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallEvaded / (overallSwings) * 100)));
2249 else
2250 CombatStatsGeneralEvadedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2251 end
2252  
2253 CombatStatsGeneralDeflectedTextLabel:SetText(overallDeflected);
2254  
2255 if(overallDeflected ~= 0) then
2256 CombatStatsGeneralDeflectedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallDeflected / (overallSwings) * 100)));
2257 else
2258 CombatStatsGeneralDeflectedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
2259 end
2260  
2261 --
2262 -- Percent of total damage
2263 --
2264  
2265 if(totalHits ~=0) then
2266 CombatStatsGeneralPercentDmgPctLabel:SetText( format("%.2f %%", ((overallRegDmg + overallCritDmg ) / totalDamage) * 100) );
2267 else
2268 CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
2269 end
2270  
2271 --
2272 -- Time since last crit
2273 --
2274  
2275 local timeNow;
2276 timeNow = GetTime();
2277  
2278 if(overallLastcrit ~= 0) then
2279 CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE ..Clock_FormatTime( (timeNow - overallLastcrit)));
2280 else
2281 CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE.."N/A");
2282 end
2283  
2284 --
2285 -- Attack Crit %
2286 --
2287  
2288 if (totalHits ~= 0) and (overallCrits ~= 0) then
2289 CombatStatsAttackCritPctLabel:SetText(format(RED_FONT_COLOR_CODE.."%.1f%%", ( (overallCrits) / (totalHits)) * 100.0 ));
2290 else
2291 CombatStatsAttackCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
2292 end
2293  
2294 --
2295 -- Attack Non Crit %
2296 --
2297  
2298 if (totalHits ~= 0) and (overallNonCrits ~= 0) then
2299 CombatStatsAttackNonCritPctLabel:SetText( format(GREEN_FONT_COLOR_CODE.."%.1f%%", ( (overallNonCrits) / (totalHits)) * 100.0 ));
2300 else
2301 CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."0.0 %");
2302 end
2303  
2304 --
2305 -- Non Crit stats
2306 --
2307  
2308 CombatStatsNonCritHitsStatText:SetText(overallNonCrits);
2309 CombatStatsNonCritDamageStatText:SetText(overallRegDmg);
2310 CombatStatsNonCritMinMaxStatText:SetText(overallminReg .." / "..overallmaxReg);
2311  
2312 if( overallRegDmg ~= 0) then
2313  
2314 if( (totalHits - overallCrits) < 0) then
2315 CombatStatsNonCritAvgStatText:SetText(format("%.1f", overallRegDmg / (overallCrits - totalHits ) ));
2316 end
2317  
2318 if( (totalHits - overallCrits) == 0 ) then
2319 CombatStatsNonCritAvgStatText:SetText(format("%1.f", overallRegDmg / (overallCrits) ));
2320 end
2321  
2322 if( (totalHits - overallCrits) > 0 ) then
2323 CombatStatsNonCritAvgStatText:SetText(format("%1.f", overallRegDmg / (totalHits - overallCrits) ));
2324 end
2325  
2326 else
2327 CombatStatsNonCritAvgStatText:SetText("0.0");
2328 end
2329  
2330 if(overallNonCrits ~=0) then
2331 CombatStatsNonCritPercentDamageStatText:SetText( format("%.2f %%", ( overallRegDmg / (overallRegDmg + overallCritDmg )) * 100.0));
2332 else
2333 CombatStatsNonCritPercentDamageStatText:SetText("0.0 %");
2334 end
2335  
2336 --
2337 -- Crit stats
2338 --
2339  
2340 CombatStatsCritHitsStatText:SetText(overallCrits);
2341 CombatStatsCritDamageStatText:SetText(overallCritDmg);
2342 CombatStatsCritMinMaxStatText:SetText(overallminCrit .." / "..overallmaxCrit);
2343  
2344 if( overallCritDmg ~= 0) then
2345 CombatStatsCritAvgStatText:SetText(format("%1.f", (overallCritDmg / overallCrits) ));
2346 else
2347 CombatStatsCritAvgStatText:SetText("0.0");
2348 end
2349  
2350 if(overallCrits ~=0) then
2351 CombatStatsCritPercentDamageStatText:SetText(format("%.2f %%", (overallCritDmg / ( overallRegDmg + overallCritDmg )) * 100.10 ));
2352 else
2353 CombatStatsCritPercentDamageStatText:SetText("0.0 %");
2354 end
2355  
2356 end
2357  
2358 end
2359  
2360  
2361 --
2362 -- Time functions
2363 -- from Clock.lua
2364 --
2365  
2366 local function Clock_FormatPart(fmt, val)
2367 local part;
2368  
2369 part = format(TEXT(fmt), val);
2370 if( val ~= 1 ) then
2371 part = part.."s";
2372 end
2373  
2374 return part;
2375 end
2376  
2377 function Clock_FormatTime(time)
2378 local d, h, m, s;
2379 local text = "";
2380 local skip = 1;
2381  
2382 if ( time == 0 ) then return Clock_FormatPart(CLOCK_TIME_SECOND, 0); end
2383  
2384 d, h, m, s = ChatFrame_TimeBreakDown(time);
2385 if( d > 0 ) then
2386 text = text..Clock_FormatPart(CLOCK_TIME_DAY, d)..", ";
2387 skip = 0;
2388 end
2389 if( (skip == 0) or (h > 0) ) then
2390 text = text..Clock_FormatPart(CLOCK_TIME_HOUR, h)..", ";
2391 skip = 0;
2392 end
2393 if( (skip == 0) or (m > 0) ) then
2394 text = text..Clock_FormatPart(CLOCK_TIME_MINUTE, m)..", ";
2395 skip = 0;
2396 end
2397 if( (skip == 0) or (s > 0) ) then
2398 text = text..Clock_FormatPart(CLOCK_TIME_SECOND, s);
2399 end
2400  
2401 return text;
2402 end
2403  
2404 function CombatStats_TargetFrame_OnShow()
2405 if (CombatStats_Old_TargetFrame_OnShow) then
2406 CombatStats_Old_TargetFrame_OnShow();
2407 end
2408 CombatStats_UpdateVisibility(1);
2409 end
2410  
2411 function CombatStats_TargetFrame_OnHide()
2412 if (CombatStats_Old_TargetFrame_OnHide) then
2413 CombatStats_Old_TargetFrame_OnHide();
2414 end
2415 CombatStats_UpdateVisibility(0);
2416 end