vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:

--[[

        CombatStats3 - Stat Damage Tracking
        AUTHOR: DmgInc on most forums / Glacier on official WoW forums
        THANKS TO:      The dude(ette) who made DPSPlus for showing me the light on how to parse the combat log
                                The dude(ette) who made Clock for the time conversion routines 

        Rev. 3.3        - ReEnabled the option to only show the stats on a mouseclick
        2.16.05         - DPS caluculated is now 15 seconds w/no option to change
                                - Added end of fight stats option to turn on/off
                                - Slash commands will save between sessions when not using w/cosmos
                                
        Rev. 3.2        - Added end of fight statistics
        2.09.05         - Using PLAYER_REGEN_DISABLED ENABLED to tell when you
                  are in/out of combat for end of fight info

        Rev. 3.1        - Lots of fixes to track pet stats
        2.07.05 

        Rev. 3.0        - Initial version to track Defensive DPS        
        12.xx.04

        Rev 2.03        - Now really really works w/o cosmos
        11.15.04
        
        Rev 2.02        - Now works w/o cosmos
        11.14.04        - Changed the text display frame
                        - Fixed the crit % running out of the frame when it was 100%
                        - Put "Default" attack at top of the list
                        - Added in a "Total", put it at the bottom of the list
                        - UI is now movalbe
                        - UI will update itself while you are attacking if it is visible
                        - Fixed a bug where the close "X" button couldn't be pressed
                        - Now uses OnEvent and OnUpdate 
                        - Pet damage is now tracked
                        - DOT damage totals are correctly shown
                        - Hopefully got rid of bogus entries
                                

        Rev 2.01        - First release w/new UI
        11.05.04
        
  ]]

if ( CT_AddMovable ) then
        CT_AddMovable("CombatStatsFrame", "CombatStats", "TOPLEFT", "TOPLEFT", "UIParent", 150, 0, function(status) end);
end



--
--      Cosmos Cofig variables
--

CombatStats_Config = { };
CombatStats_Config.CombatStats_OnOff = 1;
CombatStats_Config.CombatStats_HideOnNoTarget = 0;
CombatStats_Config.CombatStats_EndOfFight = 0;
CombatStats_Config.CombatStats_UseMouseOver = 0;

CombatStats_LastUpdate = 0;
CombatStats_UpdateFreq = 0.1; 
CombatStats_DPSLen = 15;        -- Calculate DPS over the last 60 seconds
 
defcritCount = 0;
speccritCount= 0;

timestamps = {};
takenTimestamps = {};

players = {};
playersTaken = {};

dmg = {};
dmgTaken = {};

dpstotals = {};
dpsTakenTotals = {};

defCrits = {0};
specCrits = {0};

defCritTotals = {};
specCritTotals = {};

bInCombat = 0;
bHasDefault = 0;

totalDamage = 0;

--
--      Last fight info
--

lastFightStart          =       0;
lastFightFinish         =        0;
lastFightPlayerDamage   =       0;
lastFightPetDamage      =       0;

mobDied                         =       0;
regenEnabled            =       0;
leaveCombat             =       0;

overallCombatTime       =       0;

overallSwings           =       0;
overallMisses           =       0;
overallDodged           =       0;
overallParried          =       0;
overallEvaded           =       0;
overallBlocked          =       0;
overallResisted         =       0;
overallImmuned          =       0;
overallDeflected        =       0;
overallHits             =       0;
overallNonCrits         =       0;
overallCrits            =       0;
overallmaxCrit          =       0;
overallminCrit          =       0;
overallmaxReg           =       0;
overallminReg           =       0;
overallRegDmg           =       0;
overallCritDmg          =       0;
overallLastcrit         =       0;


attackNames = {};
specialAttacks = {};
specialAttackLog = {};

totalHits = 0;
totalCrits = 0;
specialsCount = 0;
combatTime = 1;

CombatStats_Old_TargetFrame_OnShow = nil;
CombatStats_Old_TargetFrame_OnHide = nil;

CombatStats_ChatCommandHandlers={};

bFirstTime = 1;

CombatStatsVars = { };
CombatStatsSessionVars = { };
DeathCount = 0;
DeathLog = { };
CombatStatsRecentVars = { };
CombatStatsByName = { };
CombatStatsSessionByName = { };
CombatStatsDisplay = { };

function CombatStats_ChatCommandHandler(msg)
        msg = string.lower(msg);
        local firsti, lasti, command, setStr = string.find (msg, "(%w+) ([%w%.]+)");
        if ((not command) and msg) then
                command = msg;
        end
        if (command) then
                for curCommand in CombatStats_ChatCommandHandlers do
                        if (command == curCommand) then
                                if (setStr) then
                                        CombatStats_ChatCommandHandlers[curCommand](setStr);
                                else
                                        CombatStats_ChatCommandHandlers[curCommand]();
                                end
                                return;
                        end
                end
        end
        Print("All slash command can start with either /cs or /combatstats example: /cs enable or /combatstats enable");
        Print("Then you can pass on or off to them, or pass a number for ones that need a number ex.");
        Print("/cs enable on");
        Print("/cs enable off");
        Print("");
        Print("enable [on | off] - 'Enable/disabwle CombatStats, on or off'");
        Print("target [on | off] - 'Only show DPS meter when you have a target'");
        Print("mouseover [on | off] - 'Show detailed window on mouseover'");
        Print("endoffight [on | off] - 'Show end of fight information'");
        Print("reset yes - 'Rest all stats to 0'");

end

--
--      Slash command handler
--

function CombatStats_Enable_ChatCommandHandler(msg)

        if (msg) then
                msg = string.upper(msg);
                -- Toggle appropriately
                if (string.find(msg, "ON")) then
                        CombatStats_Config.CombatStats_OnOff = 1;
                elseif (string.find(msg, "OFF")) then
                        CombatStats_Config.CombatStats_OnOff = 0;               
                end
        end
        
        if(Cosmos_RegisterConfiguration ~= nil) then
                Cosmos_UpdateValue("COMBATSTATS_CONFIG_ONOFF", CSM_CHECKONOFF, CombatStats_Config.CombatStats_OnOff);
        end

        CombatStats_UpdateVisibility();

end
CombatStats_ChatCommandHandlers["enable"] = CombatStats_Enable_ChatCommandHandler;

function CombatStats_Target_ChatCommandHandler(msg)

        if (msg) then
                msg = string.upper(msg);
                -- Toggle appropriately
                if (string.find(msg, "ON")) then
                        CombatStats_Config.CombatStats_HideOnNoTarget = 1;
                elseif (string.find(msg, "OFF")) then
                        CombatStats_Config.CombatStats_HideOnNoTarget = 0;              
                end
        end
        
        if(Cosmos_RegisterConfiguration ~= nil) then
                Cosmos_UpdateValue("COMBATSTATS_CONFIG_HIDEONNOTARGET", CSM_CHECKONOFF, CombatStats_Config.CombatStats_HideOnNoTarget);
        end

        CombatStats_UpdateVisibility();

end
CombatStats_ChatCommandHandlers["target"] = CombatStats_Target_ChatCommandHandler;

function CombatStats_Mouseover_ChatCommandHandler(msg)

        if (msg) then
                msg = string.upper(msg);
                -- Toggle appropriately
                if (string.find(msg, "ON")) then
                        CombatStats_Config.CombatStats_UseMouseOver = 1;
                elseif (string.find(msg, "OFF")) then
                        CombatStats_Config.CombatStats_UseMouseOver = 0;                
                end
        end
        
        if(Cosmos_RegisterConfiguration ~= nil) then
                Cosmos_UpdateValue("COMBATSTATS_CONFIG_USEMOUSEOVER", CSM_CHECKONOFF, CombatStats_Config.CombatStats_UseMouseOver);
        end

        CombatStats_UpdateVisibility();

end
CombatStats_ChatCommandHandlers["mouseover"] = CombatStats_Target_ChatCommandHandler;

function CombatStats_Endoffight_ChatCommandHandler(msg)

        if (msg) then
                msg = string.upper(msg);
                -- Toggle appropriately
                if (string.find(msg, "ON")) then
                        CombatStats_Config.CombatStats_EndOfFight = 1;
                elseif (string.find(msg, "OFF")) then
                        CombatStats_Config.CombatStats_EndOfFight = 0;          
                end
        end
        
        if(Cosmos_RegisterConfiguration ~= nil) then
                Cosmos_UpdateValue("COMBATSTATS_CONFIG_ENDOFFIGHT", CSM_CHECKONOFF, CombatStats_Config.CombatStats_EndOfFight);
        end

        CombatStats_UpdateVisibility();

end
CombatStats_ChatCommandHandlers["endoffight"] = CombatStats_Target_ChatCommandHandler;

function CombatStats_Reset_ChatCommandHandler(msg)

        if (msg) then
                msg = string.upper(msg);
                -- Toggle appropriately
                if (string.find(msg, "YES")) then
                        CombatStats_Reset();
                end             
        end

end
CombatStats_ChatCommandHandlers["reset"] = CombatStats_Reset_ChatCommandHandler;

--
--      Cosmos Config Handlers
--

function CombatStats_HideOnNoTarget_OnOff(toggle)
        CombatStats_Config.CombatStats_HideOnNoTarget = toggle;
        CombatStats_UpdateVisibility();
end

function CombatStats_Watch_OnOff(toggle) 
        CombatStats_Config.CombatStats_OnOff = toggle;
        CombatStats_UpdateVisibility(); 
end

function CombatStats_UseMouseOver_OnOff(toggle)
        CombatStats_Config.CombatStats_UseMouseOver = toggle;
        CombatStats_UpdateVisibility();
end

function CombatStats_EndOfFight_OnOff(toggle)
        CombatStats_Config.CombatStats_EndOfFight = toggle;
        CombatStats_UpdateVisibility();
end


function CombatStats_UpdateVisibility(hasTarget)
        if (not hasTarget) then
                if (TargetFrame:IsVisible()) then
                        hasTarget = 1;
                else
                        hasTarget = 0;
                end
        end
        if (CombatStats_Config.CombatStats_OnOff == 1) then
                if (CombatStats_Config.CombatStats_HideOnNoTarget == 1) then
                        if (hasTarget == 1) then
                                CombatStatsFrame:Show();
                        else
                                CombatStatsFrame:Hide();
                        end
                else
                        CombatStatsFrame:Show();
                end
                
                --
                --      Register the events to watch
                --
                
                
        else
                CombatStatsFrame:Hide();
        end
end

function CombatStats_Reset()

        defcritCount = 0;
        speccritCount= 0;
        timestamps = {};
        players = {};
        dmg = {};
        dpstotals = {};
        defCrits = {0};
        specCrits = {0};
        defCritTotals = {};
        specCritTotals = {};

        totalDamage = 0;

        attackNames = {};
        specialAttacks = {};
        specialAttackLog = {};

        totalHits = 0;
        totalCrits = 0;
        specialsCount = 0;
        bHasDefault = 0;
        
        overallSwings           =       0;
        overallMisses           =       0;
        overallDodged           =       0;
        overallParried          =       0;
        overallEvaded           =       0;
        overallBlocked          =       0;
        overallResisted         =       0;
        overallImmuned          =       0;
        overallDeflected        =       0;
        overallHits                     =       0;
        overallNonCrits         =       0;
        overallCrits            =       0;
        overallmaxCrit          =       0;
        overallminCrit          =       0;
        overallmaxReg           =       0;
        overallminReg           =       0;
        overallRegDmg           =       0;
        overallCritDmg          =       0;
        overallLastcrit         =       0;
        
        CombatStatsText:SetText("Overall DPS :: ");
        
        CombatStatsGeneralNameTextLabel:SetText("N/A");
                
                CombatStatsNonCritHitsStatText:SetText("0");     
                CombatStatsNonCritDamageStatText:SetText("0");           
                CombatStatsNonCritMinMaxStatText:SetText("0 / 0");      
                CombatStatsNonCritAvgStatText:SetText("0.0");   
                CombatStatsNonCritPercentDamageStatText:SetText("0.0 %");       
        
                CombatStatsCritHitsStatText:SetText("0");
                CombatStatsCritDamageStatText:SetText("0");
                CombatStatsCritMinMaxStatText:SetText("0 / 0");
                CombatStatsCritAvgStatText:SetText("0.0");
                CombatStatsCritPercentDamageStatText:SetText("0.0 %");
        
                CombatStatsGeneralTotalHitsHits:SetText("0");    
                CombatStatsGeneralSwingsLabel:SetText("0");
                        
                CombatStatsGeneralMissesTextLabel:SetText("0");  
                CombatStatsGeneralMissesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralDodgesTextLabel:SetText("0");  
                CombatStatsGeneralDodgesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralParriedTextLabel:SetText("0"); 
                CombatStatsGeneralParriedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralBlockedTextLabel:SetText("0"); 
                CombatStatsGeneralBlockedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralResistedTextLabel:SetText("0");        
                CombatStatsGeneralResistedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralImmunedTextLabel:SetText("0"); 
                CombatStatsGeneralImmunedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralEvadedTextLabel:SetText("0");  
                CombatStatsGeneralEvadedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
                
                CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE.."N/A");
        
                CombatStatsOverallCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");           
                
                CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."0.0 %");               
                CombatStatsAttackCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
                
                UIDropDownMenu_SetText(CS_DROPDOWN_SELECT_TEXT,CombatStatsAttackDropDown);
                                
        
end


function CombatStatDPSLen(checked,value)
        CombatStats_DPSLen = value;     
end

-- Register w/ Cosmos Config and set up a chat watch
function CombatStats_RegisterCosmos()
        if( (Cosmos_RegisterConfiguration ~= nil)) then
                Cosmos_RegisterConfiguration(
                        "COS_COMBATSTATS",
                        "SECTION",
                        COMBATSTATS_CONFIG_HEADER,
                        COMBATSTATS_CONFIG_HEADER_INFO
                        );
                Cosmos_RegisterConfiguration(
                        "COS_COMBATSTATS_HEADER",
                        "SEPARATOR",
                        COMBATSTATS_CONFIG_HEADER,
                        COMBATSTATS_CONFIG_HEADER_INFO
                        );
                Cosmos_RegisterConfiguration(
                        "COS_COMBATSTATS_ONOFF", 
                        "CHECKBOX",
                        COMBATSTATS_CONFIG_ONOFF,
                        COMBATSTATS_CONFIG_ONOFF_INFO,
                        CombatStats_Watch_OnOff,
                        CombatStats_Config.CombatStats_OnOff
                        );              
                Cosmos_RegisterConfiguration(
                        "COS_COMBATSTATS_USEMOUSEOVER_ONOFF", 
                        "CHECKBOX",
                        COMBATSTATS_CONFIG_USEMOUSEOVER,
                        COMBATSTATS_CONFIG_USEMOUSEOVER_INFO,
                        CombatStats_UseMouseOver_OnOff,
                        CombatStats_Config.CombatStats_UseMouseOver,
                        0
                        );
                Cosmos_RegisterConfiguration(
                        "COS_COMBATSTATS_HIDEONNOTARGET_ONOFF", 
                        "CHECKBOX",
                        COMBATSTATS_CONFIG_HIDEONNOTARGET,
                        COMBATSTATS_CONFIG_HIDEONNOTARGET_INFO,
                        CombatStats_HideOnNoTarget_OnOff,
                        CombatStats_Config.CombatStats_HideOnNoTarget
                        );      
                Cosmos_RegisterConfiguration(
                        "COS_COMBATSTATS_ENDOFFIGHT_ONOFF", 
                        "CHECKBOX",
                        COMBATSTATS_CONFIG_ENDOFFIGHT,
                        COMBATSTATS_CONFIG_ENDOFFIGHT_INFO,
                        CombatStats_EndOfFight_OnOff,
                        CombatStats_Config.CombatStats_EndOfFight
                        );      

                                                
                Cosmos_RegisterChatCommand (
                        "COMBATSTATS_COMMANDS",
                        {"/cs", "/combatsats"},
                        CombatStats_ChatCommandHandler,
                        CS_CHAT_COMMAND_INFO
                        );                                      
        end

end

function ShowLastFightDPS()

        --
        --      Show the last fight DPS
        --
        
        local totalFightTime
        local playerDPS
        local petDPS
        local petPct
        local playerText = "%.1f sec.\nTotal Damage :  %d\nOverall Fight DPS : %.1f\n";
        local petText = "Your pet did %d or %.1f%% of your overall damage.\nPet DPS : %.1f";
        local text = "Fight Statistics\nDuration : ";
        
        
        if( (bInCombat == 0) and (lastFightFinish > lastFightStart)) then
                        
                totalFightTime = lastFightFinish - lastFightStart;
                petDPS = lastFightPetDamage / totalFightTime;
                playerDPS = lastFightPlayerDamage / totalFightTime;
                
                if(lastFightPetDamge ~=0) then
                        petPct =  (lastFightPetDamage / lastFightPlayerDamage) * 100;
                end
                
                text = text ..format(playerText, totalFightTime,lastFightPlayerDamage,playerDPS);
                
                if(lastFightPetDamage ~= 0) then                
                        text = text ..format(petText,lastFightPetDamage,petPct,petDPS);         
                end
                                
                if(DEFAULT_CHAT_FRAME) then
                        
                        DEFAULT_CHAT_FRAME:AddMessage(text);
                
                end
                        
        end
        
        
end

function CombatStats_OnEvent()

        --
        --      Don't do all this unless
        --      combat stats is turned on
        --
        
        if ( not CombatStats_Config.CombatStats_OnOff ) then
                return;
        end
        
                        
        if (event == "PLAYER_REGEN_ENABLED") then
                regenEnabled = GetTime();
                if( (lastFightPlayerDamage > 0) and (bInCombat == 1) ) then
                        lastFightFinish = GetTime();
                        bInCombat = 0;                                  
                        if(CombatStats_Config.CombatStats_EndOfFight  == 1) then
                                ShowLastFightDPS();
                        end
                end
                
        end

--      if (event == "PLAYER_LEAVE_COMBAT") then
--              leaveCombat = GetTime();
--              if( (lastFightPlayerDamage > 0) and (bInCombat == 1) ) then
--                      lastFightFinish = GetTime();
--                      bInCombat = 0;                                  
--                      if(CombatStats_Config.CombatStats_EndOfFight  == 1) then
--                              ShowLastFightDPS();
--                      end
--              end
--      end
        
        if (event == "PLAYER_REGEN_DISABLED") then      
                if (bInCombat == 0) then
                        lastFightStart = GetTime();
                        bInCombat = 1;                  
                        lastFightPlayerDamage = 0;
                        lastFightPetDamage = 0;                 
                end                                                             
        end     
        
        local p, d;
        local curtime = combatTime;
        
        if(     event == "CHAT_MSG_COMBAT_SELF_HITS" 
                or event == "CHAT_MSG_COMBAT_SELF_MISSES"
                or event == "CHAT_MSG_SPELL_SELF_DAMAGE"
                or event == "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE"
                or event == "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE"
                ) then                  

                for creatureName, damage,damageType, spell in string.gfind(arg1, "(.+) suffers (%d+) (.+) damage from your (.+).") do
                        CombatStats_AddSpecialData(spell,"dot",damage,curtime);                 
                        CombatStats_AddDPSEntry("Your", damage);                        
                        return;
                end
                
                for spell, creatureName, damage in string.gfind(arg1, "Your (.+) hits (.+) for (%d+).") do
                        CombatStats_AddSpecialData(spell,"hit",damage,curtime);
                        CombatStats_AddDPSEntry("Your", damage);
                        return;
                end

                for creatureName, damage in string.gfind(arg1, "You hit (.+) for (%d+)") do
                        CombatStats_AddSpecialData("Default","hit",damage,curtime);
                        CombatStats_AddDPSEntry("Your", damage);
                        return;
                end
                for spell, creatureName, damage in string.gfind(arg1, "Your (.+) crits (.+) for (%d+).") do
                        CombatStats_AddSpecialData(spell,"crit",damage,curtime);
                        CombatStats_AddDPSEntry("Your", damage);
                        return;
                end
                for creatureName, damage in string.gfind(arg1, "You crit (.+) for (%d+)") do
                        CombatStats_AddSpecialData("Default","crit",damage,curtime);
                        CombatStats_AddDPSEntry("Your", damage);
                        return;
                end
                for creatureName in string.gfind(arg1, "You miss (.+).") do
                        CombatStats_AddSpecialData("Default","miss",0,curtime);
                        return;
                end
                for creatureName in string.gfind(arg1, "You attack. (.+) parries.") do
                        CombatStats_AddSpecialData("Default","parry",0,curtime);
                        return;
                end
                for creatureName in string.gfind(arg1, "You attack. (.+) evades.") do
                        CombatStats_AddSpecialData("Default","evade",0,curtime);
                        return;
                end
                for creatureName in string.gfind(arg1, "You attack. (.+) dodges.") do
                        CombatStats_AddSpecialData("Default","dodge",0,curtime);
                        return;
                end
                for creatureName in string.gfind(arg1, "You attack. (.+) deflects.") do
                        CombatStats_AddSpecialData("Default","deflect",0,curtime);
                        return;
                end
                for creatureName in string.gfind(arg1, "You attack. (.+) blocks.") do
                        CombatStats_AddSpecialData("Default","block",0,curtime);
                        return;
                end
                for spell, creatureName in string.gfind(arg1, "Your (.+) was blocked by (.+).") do
                        CombatStats_AddSpecialData(spell,"block",0,curtime);
                        return;
                end
                for spell, creatureName in string.gfind(arg1, "Your (.+) was deflected by (.+).") do
                        CombatStats_AddSpecialData(spell,"deflect",0,curtime);
                        return;
                end
                for spell, creatureName in string.gfind(arg1, "Your (.+) was dodged by (.+).") do
                        CombatStats_AddSpecialData(spell,"dodge",0,curtime);
                        return;
                end
                for spell, creatureName in string.gfind(arg1, "Your (.+) was evaded by (.+).") do
                        CombatStats_AddSpecialData(spell,"evade",0,curtime);
                        return;
                end
                for spell, creatureName in string.gfind(arg1, "Your (.+) is parried by (.+)") do
                        CombatStats_AddSpecialData(spell,"parry",0,curtime);
                        return;
                end
                for spell, creatureName in string.gfind(arg1, "Your (.+) was resisted by (.+).") do
                        CombatStats_AddSpecialData(spell,"resist",0,curtime);
                        return;
                end
                for spell, creatureName in string.gfind(arg1, "Your (.+) failed. (.+) is immune.") do
                        CombatStats_AddSpecialData(spell,"immune",0,curtime);
                        return;
                end
                for spell, creatureName in string.gfind(arg1, "Your (.+) missed (.+).") do
                        CombatStats_AddSpecialData(spell,"miss",0,curtime);
                        return;
                end
                
        end
        
        if(     event == "CHAT_MSG_COMBAT_PET_HITS" ) then
                
                bInCombat = 1;
                
                for petName, creatureName, damage in string.gfind(arg1, "(.+) crits (.+) for (%d+).") do
                        CombatStats_AddSpecialData("[Pet] Default","crit",damage,curtime);
                        CombatStats_AddDPSEntry("Your", damage);
                        return;
                end
                
                for petName, creatureName, damage in string.gfind(arg1, "(.+) hits (.+) for (%d+).") do
                        CombatStats_AddSpecialData("[Pet] Default","hit",damage,curtime);
                        CombatStats_AddDPSEntry("Your", damage);
                        return;
                end
        end

        if (event == "CHAT_MSG_SPELL_PET_DAMAGE") then

                for petName, spell, creatureName, damage in string.gfind(arg1, "(.+)'s (.+) hits (.+) for (%d+).") do                   
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"hit",damage,curtime);
                                CombatStats_AddDPSEntry("Your", damage);
                        end
                        return;
                end
                
                for petName, spell, creatureName, damage in string.gfind(arg1, "(.+)'s (.+) crits (.+) for (%d+).") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"crit",damage,curtime);
                                CombatStats_AddDPSEntry("Your", damage);
                        end
                        return;
                end
                
                for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was blocked by (.*).") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"block",0,curtime);                          
                        end
                        return;
                end
                
                for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was dodged by (.*).") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"dodge",0,curtime);                          
                        end                     
                        return;
                end
  
        for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was evaded by (.*).") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"evade",0,curtime);                          
                        end                     
                        return;
                end

       for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) fails. (.+) is immune.") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"immune",0,curtime);                         
                        end                                             
                        return;
                end
        
                for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was resisted by (.*).") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"resist",0,curtime);                         
                        end                                             
                        return;
                end

        for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) misses (.*).") do
                if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"miss",0,curtime);                           
                        end                                             
                        return;
                end
                
                for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) missed (.*).") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"miss",0,curtime);                           
                        end                                             
                        return;
                end
                
                for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) failed. (.+) is immune.") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"immune",0,curtime);
                        end
                        return;
                end
                for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) missed (.+).") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"miss",0,curtime);
                        end
                        return;
                end
                for petName, spell, creatureName in string.gfind(arg1, "(.+)'s (.+) was deflected by (.+).") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] "..spell,"deflect",0,curtime);
                        end
                        return;
                end     
                
        end
        
        if (event == "CHAT_MSG_COMBAT_PET_MISSES") then

                bInCombat = 1;  
        
                for petName, creatureName in string.gfind(arg1, "(.+) misses (.*).") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] Default","miss",0,curtime);
                        end     
                        return;
                end
                
                for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) parries.") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] Default","parry",0,curtime);
                        end
                        return;
                end
                for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) evades.") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] Default","evade",0,curtime);
                        end
                        return;
                end
                for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) dodges.") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] Default","dodge",0,curtime);
                        end
                        return;
                end
                for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) deflects.") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] Default","deflect",0,curtime);
                        end
                        return;
                end
                for petName, creatureName in string.gfind(arg1, "(.+) attacks. (.+) blocks.") do
                        if (petName == UnitName('pet') or petName == 'your pet') then
                                CombatStats_AddSpecialData("[Pet] Default","block",0,curtime);
                        end
                        return;
                end
                
                
        end
        
        if(event == "CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS") then

                bInCombat = 1;
        
                for creatureName, damage,tmpStr in string.gfind(arg1, "(.+) hits you for (%d+). (.+) blocked") do
                        CombatStats_AddDefDPSEntry("Your",damage);
                        CombatStats_AddSpecialData("Defensive","hit",damage,curtime);
                        CombatStats_AddSpecialData("Defensive","block",0,curtime);                      
                        return;
                end
                for creatureName, damage in string.gfind(arg1, "(.+) hits you for (%d+)") do
                        CombatStats_AddDefDPSEntry("Your",damage);
                        CombatStats_AddSpecialData("Defensive","hit",damage,curtime);                   
                        return;
                end
                for creatureName, damage in string.gfind(arg1, "(.+) crits you for (%d+).") do
                        CombatStats_AddDefDPSEntry("Your",damage);
                        CombatStats_AddSpecialData("Defensive","crit",damage,curtime);
                        return;
                end
        
        end
        
        if( event == "CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE") then


                for creatureName, spell, damage in string.gfind(arg1, "(.+)'s (.+) hits you for (%d+).") do
                        CombatStats_AddDefDPSEntry("Your",damage);
                        CombatStats_AddSpecialData("Defensive","hit",damage,curtime);
                        return;
                end
                
                for creatureName, spell, damage in string.gfind(arg1, "(.+)'s (.+) crits you for (%d+).") do
                        CombatStats_AddDefDPSEntry("Your",damage);
                        CombatStats_AddSpecialData("Defensive","crit",damage,curtime);
                        return;
                end
             
                for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was blocked%.") do
                        CombatStats_AddSpecialData("Defensive","block",0,curtime);
                        return;
                end
                for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was deflected%.") do
                        CombatStats_AddSpecialData("Defensive","deflect",0,curtime);
                        return;
                end
                for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was dodged%.") do
                        CombatStats_AddSpecialData("Defensive","dodge",0,curtime);
                        return;
                end
                for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was evaded%.") do
                        CombatStats_AddSpecialData("Defensive","evade",0,curtime);
                        return;
                end
                for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) failed. You are immune.") do
                        CombatStats_AddSpecialData("Defensive","immune",0,curtime);
                        return;
                end
                for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) misses you.") do
                        CombatStats_AddSpecialData("Defensive","miss",0,curtime);
                        return;
                end
                for creatureName, spell in string.gfind(arg1, "You parry (.+)'s (.+)") do
                        CombatStats_AddSpecialData("Defensive","parry",0,curtime);
                        return;
                end
                for creatureName, spell in string.gfind(arg1, "(.+)'s (.+) was resisted%.") do
                        CombatStats_AddSpecialData("Defensive","resist",0,curtime);
                        return;
                end
        end
        if (event == "CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES") then

                
                for creatureName in string.gfind(arg1, "(.+) misses you.") do
                        CombatStats_AddSpecialData("Defensive","miss",0,curtime);
                        return;
                end
                for creatureName in string.gfind(arg1, "(.+) attacks. You parry.") do
                        CombatStats_AddSpecialData("Defensive","parry",0,curtime);
                        return;
                end
                for creatureName in string.gfind(arg1, "(.+) attacks. You evade.") do
                        CombatStats_AddSpecialData("Defensive","evade",0,curtime);                      
                        return;
                end
                for creatureName in string.gfind(arg1, "(.+) attacks. You dodge.") do
                        CombatStats_AddSpecialData("Defensive","dodge",0,curtime);
                        return;
                end
                for creatureName in string.gfind(arg1, "(.+) attacks. You deflect.") do
                        CombatStats_AddSpecialData("Defensive","deflect",0,curtime);
                        return;
                end
                for creatureName in string.gfind(arg1, "(.+) attacks. You block.") do
                        CombatStats_AddSpecialData("Defensive","block",0,curtime);
                        return;
                end
        end

        if ( event == "CHAT_MSG_SPELL_SELF_BUFF" or event == "CHAT_MSG_SPELL_PARTY_BUFF" or event == "CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF" ) then
                local useless, useless, spell, amount = string.find(arg1, "Your (.+) critically heals .+ for (%d+)%.");
                if ( spell and amount ) then
                        CombatStats_AddSpecialData("[Heal] Total","crit",amount,curtime, 1);
                        CombatStats_AddSpecialData("[Heal] "..spell,"crit",amount,curtime, 1);          
                elseif ( string.find(arg1, "Your (.+) heals .+ for (%d+)%.") ) then
                        local useless, useless, spell, amount = string.find(arg1, "Your (.+) heals .+ for (%d+)%.");
                        if ( spell and amount ) then
                                CombatStats_AddSpecialData("[Heal] Total","hit",amount,curtime, 1);
                                CombatStats_AddSpecialData("[Heal] "..spell,"hit",amount,curtime, 1);
                        end
                end
        end

        if ( event == "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS" or event == "CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS" ) then
                local useless, useless, amount, spell = string.find(arg1, ".+ gains (%d+) health from your (.+)%.");
                if ( spell and amount ) then
                        CombatStats_AddSpecialData("[Heal] Total","hit",amount,curtime, 1);
                        CombatStats_AddSpecialData("[Heal] "..spell,"hot",amount,curtime, 1);           
                end
        end
        if ( event == "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS" ) then
                local useless, useless, amount, spell = string.find(arg1, "You gain (%d+) health from (.+)%.");
                if ( not string.find(arg1, "'s") and spell and amount ) then
                        CombatStats_AddSpecialData("[Heal] Total","hit",amount,curtime, 1);
                        CombatStats_AddSpecialData("[Heal] "..spell,"hot",amount,curtime, 1);           
                end
        end
end

--
--      Add/Check for attack(s)
--

function CombatStats_AddSpecialData(specialName,type,dmg,time, heal)
                
        
        --
        --      If we haven't logged this attack
        --      Create a record in the table for it
        --              

        --print2("Adding : "..specialName .." with damage : "..dmg.."at : "..time);     
                        
        if(specialName ~= "Defensive" and not heal ) then
                lastFightPlayerDamage = lastFightPlayerDamage + dmg;
                totalDamage = totalDamage + dmg;
        end
        
        for creatureName,tempJunk in string.gfind(specialName, "(.+)Pet(.+)") do
        --      print2("creatureName : "..creatureName);
        --      print2("tempJunk : "..tempJunk);
        --      print2("Adding pet special : "..specialName.. " with damage of : "..dmg);
                lastFightPetDamage = lastFightPetDamage + dmg;
        end
        
        if (type == "dot") then
                specialName = specialName .." [DOT]";
        elseif ( type == "hot" ) then
                specialName = specialName .." [HOT]";
        end

        if(specialName == "Default") then
                bHasDefault = 1;
        end
        
        if ( not specialAttacks[specialName] ) then
                specialsCount = specialsCount + 1;
                table.insert(attackNames,specialName);
                
                specialAttackLog[specialsCount] = {
                        index                           =       specialsCount,
                        name                            =       specialName,
                        isDOT                           =       0,
                        dotDmg                          =       0,
                        dotTicks                        =       0,
                        totalSwings                     =       0,
                        totalMisses                     =       0,
                        totalDodged                     =       0,
                        totalParried            =       0,
                        totalEvaded                     =       0,
                        totalBlocked            =       0,
                        totalResisted           =       0,
                        totalImmuned            =       0,
                        totalDeflected          =       0,
                        totalHits                       =       0,
                        totalNonCrits           =       0,
                        totalCrits                      =       0,
                        maxCrit                         =       0,
                        minCrit                         =       0,
                        maxReg                          =       0,
                        minReg                          =       0,
                        totalRegDmg                     =       0,
                        totalCritDmg            =       0,
                        lastCrit                        =       0,
                }
                
                specialAttacks[specialName]     = specialAttackLog[specialsCount];
                
                local info;
                
                info = {};
                info.text = specialName;
                info.func = CombatStatsAttack_OnClick;
                UIDropDownMenu_AddButton(info);
                                
        end
        
        --
        --      Now add the data
        --


        if(specialName ~= "Defensive" and not heal ) then       
                specialAttacks[specialName].totalSwings = specialAttacks[specialName].totalSwings + 1;  
                overallSwings = overallSwings + 1;
        
                if(type == "crit") then
                
                        totalHits = totalHits + 1;
                        totalCrits = totalCrits + 1;
                        specialAttacks[specialName].totalCrits = specialAttacks[specialName].totalCrits +1;
                        specialAttacks[specialName].totalCritDmg = specialAttacks[specialName].totalCritDmg + dmg;
                        specialAttacks[specialName].lastCrit = time;    
                        specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
                
                        overallCrits = overallCrits + 1;
                        overallCritDmg = overallCritDmg + dmg;
                        overallLastcrit = time;
                                
                        --
                        --      Set the initial min/max         
                        --
                
                        if(specialAttacks[specialName].maxCrit == 0) then
                                specialAttacks[specialName].maxCrit = dmg;
                        end
                
                        if(specialAttacks[specialName].minCrit == 0) then
                                specialAttacks[specialName].minCrit = dmg;
                        end
                
                        if(overallmaxCrit == 0) then
                                overallmaxCrit = dmg;
                        end
                
                        if(overallminCrit == 0) then
                                overallminCrit = dmg;
                        end
                
                        --
                        --      Check to see if this dmg
                        --      is a new min or max
                        --
                                
                        if(tonumber(dmg) < tonumber(specialAttacks[specialName].minCrit)) then
                                specialAttacks[specialName].minCrit = dmg;
                        end
                
                        if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxCrit)) then
                                specialAttacks[specialName].maxCrit = dmg;
                        end     
                
                        if(tonumber(dmg) < tonumber(overallminCrit)) then
                                overallminCrit = dmg;
                        end
                
                        if(tonumber(dmg) > tonumber(overallmaxCrit)) then
                                overallmaxCrit = dmg;
                        end     
                
                end
        
                if(type == "hit") then
                
                        totalHits = totalHits + 1;
                        specialAttacks[specialName].isDOT = 0;
                        specialAttacks[specialName].totalNonCrits = specialAttacks[specialName].totalNonCrits +1;
                        specialAttacks[specialName].totalRegDmg = specialAttacks[specialName].totalRegDmg + dmg;
                        specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
                
                        overallNonCrits = overallNonCrits + 1;
                        overallRegDmg = overallRegDmg + dmg;
                
                        --
                        --      Set the initial min/max         
                        --
                
                        if(specialAttacks[specialName].maxReg == 0) then
                                specialAttacks[specialName].maxReg = dmg;
                        end
                
                        if(specialAttacks[specialName].minReg == 0) then
                                specialAttacks[specialName].minReg = dmg;
                        end
                
                        if(overallmaxReg == 0) then
                                overallmaxReg = dmg;
                        end
                
                        if(overallminReg == 0) then
                                overallminReg = dmg;
                        end
                
                        --
                        --      Check to see if this dmg
                        --      is a new min or max
                        --
                
                        if(tonumber(dmg) < tonumber(specialAttacks[specialName].minReg)) then
                                specialAttacks[specialName].minReg = dmg;
                        end
                
                        if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxReg)) then
                                specialAttacks[specialName].maxReg = dmg;
                        end
                
                        if(tonumber(dmg) < tonumber(overallminReg)) then
                                overallminReg = dmg;
                        end
                
                        if(tonumber(dmg) > tonumber (overallmaxReg)) then
                                overallmaxReg = dmg;
                        end     
                
                end
        
                if(type == "dot") then
                
                        totalHits = totalHits + 1;
                        specialAttacks[specialName].isDOT = 1;
                        specialAttacks[specialName].dotTicks = specialAttacks[specialName].dotTicks +1;
                        specialAttacks[specialName].dotDmg = specialAttacks[specialName].dotDmg + dmg;
                        specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;              
                
                        overallNonCrits = overallNonCrits + 1;
                        overallRegDmg = overallRegDmg + dmg;
                
                        --
                        --      Set the initial min/max         
                        --
                
                        if(specialAttacks[specialName].maxReg == 0) then
                                specialAttacks[specialName].maxReg = dmg;
                        end
                        
                        if(specialAttacks[specialName].minReg == 0) then
                                specialAttacks[specialName].minReg = dmg;
                        end
                
                        if(overallmaxReg == 0) then
                                overallmaxReg = dmg;
                        end
                
                        if(overallminReg == 0) then
                                overallminReg = dmg;
                        end
                
                        --
                        --      Check to see if this dmg
                        --      is a new min or max
                        --
                
                        if(tonumber(dmg) < tonumber(specialAttacks[specialName].minReg)) then
                                specialAttacks[specialName].minReg = dmg;
                        end
                
                        if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxReg)) then
                                specialAttacks[specialName].maxReg = dmg;
                        end
                
                        if(tonumber(dmg) < tonumber(overallminReg)) then
                                overallminReg = dmg;
                        end
                
                        if(tonumber(dmg) > tonumber (overallmaxReg)) then
                                overallmaxReg = dmg;
                        end     
                
                end
                 
                if(type == "miss") then
                
                        specialAttacks[specialName].totalMisses =       specialAttacks[specialName].totalMisses + 1;
                        overallMisses = overallMisses +1;
                        
                end
        
                if(type == "dodge") then
                        
                        specialAttacks[specialName].totalDodged =       specialAttacks[specialName].totalDodged + 1;
                        overallDodged = overallDodged + 1;
                
                end
        
                if(type == "parry") then
                        
                        specialAttacks[specialName].totalParried =      specialAttacks[specialName].totalParried + 1;
                        overallParried = overallParried + 1;
                
                end
        
                if(type == "block") then
                
                        specialAttacks[specialName].totalBlocked =      specialAttacks[specialName].totalBlocked + 1;
                        overallBlocked = overallBlocked + 1;
        
                end
        
                if(type == "evade") then
                
                        specialAttacks[specialName].totalEvaded =       specialAttacks[specialName].totalEvaded + 1;
                        overallEvaded = overallEvaded + 1;
                
                end
        
                if(type == "resist") then
                        
                        specialAttacks[specialName].totalResisted =     specialAttacks[specialName].totalResisted + 1;
                        overallResisted = overallResisted + 1;
                        
                end
        
                if(type == "immune") then
                
                        specialAttacks[specialName].totalImmuned =      specialAttacks[specialName].totalImmuned + 1;
                        overallImmuned = overallImmuned + 1;
                
                end
        
                if(type == "deflect") then
                        
                        specialAttacks[specialName].totalDeflected =    specialAttacks[specialName].totalDeflected + 1;
                        overallDeflected = overallDeflected + 1;
                
                end
        
        else
        
                --
                --      Defesnsive info
                --      Don't add to overall stats and overa
                --
                
                specialAttacks[specialName].totalSwings = specialAttacks[specialName].totalSwings + 1;
                
                if(type == "crit") then
                
                        specialAttacks[specialName].totalCrits = specialAttacks[specialName].totalCrits +1;
                        specialAttacks[specialName].totalCritDmg = specialAttacks[specialName].totalCritDmg + dmg;
                        specialAttacks[specialName].lastCrit = time;    
                        specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
                                                
                        --
                        --      Set the initial min/max         
                        --
                
                        if(specialAttacks[specialName].maxCrit == 0) then
                                specialAttacks[specialName].maxCrit = dmg;
                        end
                
                        if(specialAttacks[specialName].minCrit == 0) then
                                specialAttacks[specialName].minCrit = dmg;
                        end
                                
                        --
                        --      Check to see if this dmg
                        --      is a new min or max
                        --
                                
                        if(tonumber(dmg) < tonumber(specialAttacks[specialName].minCrit)) then
                                specialAttacks[specialName].minCrit = dmg;
                        end
                
                        if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxCrit)) then
                                specialAttacks[specialName].maxCrit = dmg;
                        end                     
                
                end
        
                if(type == "hit") then
                
                        specialAttacks[specialName].isDOT = 0;
                        specialAttacks[specialName].totalNonCrits = specialAttacks[specialName].totalNonCrits +1;
                        specialAttacks[specialName].totalRegDmg = specialAttacks[specialName].totalRegDmg + dmg;
                        specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
                                
                        --
                        --      Set the initial min/max         
                        --
                
                        if(specialAttacks[specialName].maxReg == 0) then
                                specialAttacks[specialName].maxReg = dmg;
                        end
                
                        if(specialAttacks[specialName].minReg == 0) then
                                specialAttacks[specialName].minReg = dmg;
                        end
                        
                        --
                        --      Check to see if this dmg
                        --      is a new min or max
                        --
                
                        if(tonumber(dmg) < tonumber(specialAttacks[specialName].minReg)) then
                                specialAttacks[specialName].minReg = dmg;
                        end
                
                        if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxReg)) then
                                specialAttacks[specialName].maxReg = dmg;
                        end                     
                
                end

                if(type == "hot") then
                        specialAttacks[specialName].isDOT = 2;
                        specialAttacks[specialName].dotTicks = specialAttacks[specialName].dotTicks +1;
                        specialAttacks[specialName].dotDmg = specialAttacks[specialName].dotDmg + dmg;
                        specialAttacks[specialName].totalHits = specialAttacks[specialName].totalHits + 1;
                
                        --
                        --      Set the initial min/max         
                        --
                
                        if(specialAttacks[specialName].maxReg == 0) then
                                specialAttacks[specialName].maxReg = dmg;
                        end
                        
                        if(specialAttacks[specialName].minReg == 0) then
                                specialAttacks[specialName].minReg = dmg;
                        end
                
                
                        --
                        --      Check to see if this dmg
                        --      is a new min or max
                        --
                
                        if(tonumber(dmg) < tonumber(specialAttacks[specialName].minReg)) then
                                specialAttacks[specialName].minReg = dmg;
                        end
                
                        if(tonumber(dmg) > tonumber(specialAttacks[specialName].maxReg)) then
                                specialAttacks[specialName].maxReg = dmg;
                        end     
                
                end
                
                if(type == "miss") then         
                        specialAttacks[specialName].totalMisses =       specialAttacks[specialName].totalMisses + 1;
                end
        
                if(type == "dodge") then
                        specialAttacks[specialName].totalDodged =       specialAttacks[specialName].totalDodged + 1;
                end
        
                if(type == "parry") then
                        specialAttacks[specialName].totalParried =      specialAttacks[specialName].totalParried + 1;
                end
        
                if(type == "block") then
                        specialAttacks[specialName].totalBlocked =      specialAttacks[specialName].totalBlocked + 1;
                end
        
                if(type == "evade") then
                        specialAttacks[specialName].totalEvaded =       specialAttacks[specialName].totalEvaded + 1;
                end
        
                if(type == "resist") then
                        specialAttacks[specialName].totalResisted =     specialAttacks[specialName].totalResisted + 1;
                end
        
                if(type == "immune") then
                        specialAttacks[specialName].totalImmuned =      specialAttacks[specialName].totalImmuned + 1;
                end
        
                if(type == "deflect") then
                        specialAttacks[specialName].totalDeflected =    specialAttacks[specialName].totalDeflected + 1;
                end
                
        end
        if ( CombatStatsDataFrame.currAttack and CombatStatsDataFrame.currAttack == specialName ) then
                CombatStats_UpdateDetails(specialName);
        end
                                                
end

-- CombatStats Event Watcher
--
-- Update Handler
--


function CombatStats_OnUpdate(elapsed)
        local curtime = GetTime();
        local oldesttime = 0;
        local oldesttimeTaken = 0;
        local deleteindex = 0;
        local deleteindexTaken = 0;
        local playerFrame;
        if ( bInCombat == 1 ) then
                combatTime = combatTime + elapsed;
        end
        --print2("In Combat == " ..bInCombat);

        
        
        
        if (bInCombat == 1) then

                -- Check to see if its time to update the on screen DPS and only update if there are dps entries to save CPU
                if ( ((curtime - CombatStats_LastUpdate) > CombatStats_UpdateFreq) and (table.getn(timestamps) > 0) ) then
        
                        -- TODO: Change this to a high to low loop so we can do our subtracts and deletes in the same run
                        
                        --
                        --      Offensive
                        --
                
                        for k,v in pairs(timestamps) do
                                
                                -- Get rid of old dps entries and adjust the totals                             
                                if ( (curtime - CombatStats_DPSLen) > v ) then

                                        -- Subtract this entry from the totals
                                        dpstotals[players[k]] = dpstotals[players[k]] - dmg[k];                                 
                                
                                        -- Mark for later removal *We can't do the remove here cause table.remove reindexes the list and bones our loop
                                        deleteindex = k;
                                else
                                        -- were into the good stuff now, stop
                                        oldesttime = v;
                                        break;
                                end
                        end
                                        
                        
                        -- Remove entries from deleteindex down so we don't miss em
                        while (deleteindex > 0) do
                                table.remove(timestamps, deleteindex);
                                table.remove(players, deleteindex);
                                table.remove(dmg, deleteindex);
                                deleteindex = deleteindex -1;
                        end
                        
                end
                        
                if ( ((curtime - CombatStats_LastUpdate) > CombatStats_UpdateFreq) and (table.getn(takenTimestamps) > 0) ) then
                
                        --
                        --      Defensive
                        --
                        
                        for w,y in pairs(takenTimestamps) do
                        
                                -- Get rid of old dps entries and adjust the totals                             
                                if ( (curtime - CombatStats_DPSLen) > y ) then

                                        -- Subtract this entry from the totals
                                        dpsTakenTotals[playersTaken[w]] = dpsTakenTotals[playersTaken[w]] - dmgTaken[w];
                        
                                        -- Mark for later removal *We can't do the remove here cause table.remove reindexes the list and bones our loop
                                        deleteindexTaken = w;
                                else
                                        -- were into the good stuff now, stop
                                        oldesttimeTaken = y;
                                        break;
                                end
                        end
                        
                        -- Remove entries from deleteindex down so we don't miss em
                        while (deleteindexTaken > 0) do
                                table.remove(takenTimestamps, deleteindexTaken);
                                table.remove(playersTaken, deleteindexTaken);
                                table.remove(dmgTaken, deleteindexTaken);
                                deleteindexTaken = deleteindexTaken -1;
                        end
                        
                end
        
                                
                        -- NOTE: Everyone calcs off the same oldest time, not their own oldest time.
                        --       This should give more accurate dps on a per group fight basis.

        
                if ( ((curtime - CombatStats_LastUpdate) > CombatStats_UpdateFreq) and (table.getn(timestamps) > 0) ) then
                        
                        --local text = "CurTime - Oldesettime : %.1f";
                        --text = format(text,(curtime - oldesttime));
                        --print2(text);
                        
                        -- Update player DPS
                        if ( dpstotals["Your"] ~= nil ) then
                                        if(dpsTakenTotals["Your"] ~= nil) then
                                                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) )) );
                                        else                                            
                                                CombatStatsText:SetText( RED_FONT_COLOR_CODE.. "0.0" ..NORMAL_FONT_COLOR_CODE.. " / " ..GREEN_FONT_COLOR_CODE.. format(TEXT(DPS_DISPLAY), (dpstotals["Your"] / (curtime - oldesttime) )) );
                                        end
                                        
                                
                        end

                        CombatStats_LastUpdate = curtime;
                end
                
                --
                --      If the data frame is visible
                --      update the selected attack "Real time"
                --
                
                if (CombatStatsDataFrame:IsVisible()) then
                        
                        if( UIDropDownMenu_GetText(CombatStatsAttackDropDown) ~= CS_DROPDOWN_SELECT_TEXT) then
                                CombatStats_UpdateDetails( UIDropDownMenu_GetText(CombatStatsAttackDropDown));
                        end
                end
                
        end
end


-- Called from XML
function CombatStats_OnLoad()
        if ( Cosmos_RegisterConfiguration ~= nil) then 
                CombatStats_RegisterCosmos();
                HookFunction("TargetFrame_OnShow", "CombatStats_TargetFrame_OnShow", "after");
                HookFunction("TargetFrame_OnHide", "CombatStats_TargetFrame_OnHide", "after");
        else
        -- Standalone (chatwatch)
                CombatStats_Old_TargetFrame_OnShow = TargetFrame_OnShow;
                CombatStats_Old_TargetFrame_OnHide = TargetFrame_OnHide;
                TargetFrame_OnShow = CombatStats_TargetFrame_OnShow;
                TargetFrame_OnHide = CombatStats_TargetFrame_OnHide;                    
                
                SLASH_CSSLASH1 = "/combatstats";
                SLASH_CSSLASH2 = "/cs"; 
                SlashCmdList["CSSLASH"] = CombatStats_ChatCommandHandler;
                                        
        end
                
                if (not Print) then
                                setglobal("Print", function(msg, r, g, b, frame, id)
                                        if (not r) then r = 1.0; end
                                        if (not g) then g = 1.0; end
                                        if (not b) then b = 1.0; end
                                        if (not frame) then frame = DEFAULT_CHAT_FRAME; end
                                        if (frame) then
                                                if (not id) then
                                                        frame:AddMessage(msg,r,g,b);
                                                else
                                                        frame:AddMessage(msg,r,g,b,id);
                                                end
                                        end
                                end);
                        end             

                this:RegisterEvent("CHAT_MSG_COMBAT_SELF_HITS");
                this:RegisterEvent("CHAT_MSG_COMBAT_SELF_MISSES");
                this:RegisterEvent("CHAT_MSG_COMBAT_PET_HITS");
                this:RegisterEvent("CHAT_MSG_COMBAT_PET_MISSES");
                this:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE");
                this:RegisterEvent("CHAT_MSG_SPELL_PET_DAMAGE");
        
                this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE");
                this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE");
                this:RegisterEvent("CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS");
                this:RegisterEvent("CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES");
                this:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS");
                this:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES");
                
                this:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE");
                this:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE");
                this:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_BUFF");
                this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS");
                this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE");
                
                this:RegisterEvent("CHAT_MSG_SYSTEM");
                this:RegisterEvent("PLAYER_REGEN_ENABLED");
                this:RegisterEvent("PLAYER_REGEN_DISABLED");
                this:RegisterEvent("PLAYER_LEAVE_COMBAT");
                this:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN");  
                this:RegisterEvent("CHAT_MSG_COMBAT_LOG_ENEMY");
                this:RegisterEvent("CHAT_MSG_COMBAT_HOSTILE_DEATH");

                -- Heals
                this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS");
                this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS");
                this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS");

                this:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF");
                this:RegisterEvent("CHAT_MSG_SPELL_PARTY_BUFF");
                this:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF");
                        
                CombatStatsText:SetText("Overall DPS :: ");
                CombatStats_UpdateVisibility();
end

function CombatStatsAttack_OnClick()
                
        local attackID = this:GetID();
                        
        UIDropDownMenu_SetSelectedID(CombatStatsAttackDropDown, attackID);      
        --print2("GetID :: ".. UIDropDownMenu_GetSelectedID(CombatStatsAttackDropDown));
        local attackName =  UIDropDownMenu_GetText(CombatStatsAttackDropDown);
        UIDropDownMenu_SetSelectedValue(CombatStatsAttackDropDown, attackName);
        --print2("GetValue :: ".. UIDropDownMenu_GetSelectedValue(CombatStatsAttackDropDown));
        UIDropDownMenu_SetText(attackName,CombatStatsAttackDropDown);
        --this:SetText(CombatStatsDetailTypes[detailID].value);
        --this.text = CombatStatsDetailTypes[detailID].value;
        
        CombatStats_UpdateDetails(attackName);
        
end

function CombatStatsAttackDropDown_OnLoad()
        UIDropDownMenu_Initialize(this, CombatStatsAttackDropDown_Initialize);
end


function CombatStatsAttackDropDown_Initialize()
        CombatStats_LoadAttackNames();
end

function CombatStats_LoadAttackNames()

        local info;
        
        if(table.getn(attackNames) ~= 0) then   
                if(bHasDefault == 1) then
                        info = {};
                        info.text = "Default";
                        info.func = CombatStatsAttack_OnClick;
                        UIDropDownMenu_AddButton(info);
                end
        end
        
        for i=1, table.getn(attackNames), 1 do
                
                if(attackNames[i] ~= "Default") then    
                        info = {};
                        info.text = attackNames[i];
                        info.func = CombatStatsAttack_OnClick;
                        UIDropDownMenu_AddButton(info);
                end
                
        end
        
        if(table.getn(attackNames) ~= 0) then           
                info = {};
                info.text = "Total";
                info.func = CombatStatsAttack_OnClick;
                UIDropDownMenu_AddButton(info);
        end
                        
end

--
--      Add the damage to the DPS table
--

function CombatStats_AddDPSEntry(p, d)
        
        
        table.insert(timestamps, GetTime());
        table.insert(players, p);
        table.insert(dmg, d);

        -- Keep running totals on group members to shorten calculation times
        -- We'll subtract off the expired entries during OnUpdate                               
        if (dpstotals[p] == nil) then
        --      print2("dpstotals[p] == nil");
                dpstotals[p] = d;
        else
        --      print2("dpstotals[p] == " ..dpstotals[p] );
                dpstotals[p] = dpstotals[p] + d;
        --      print2("AFTER : dpstotals[p] == " ..dpstotals[p] );
        end
        
        --print2("Total : " ..dpstotals[p]);
end


--
--      Add damage taken to the DPS table
--

function CombatStats_AddDefDPSEntry(p, d)

        --print2("Adding Entry[" .. p .. "] = " .. d);  -- debug
        table.insert(takenTimestamps, GetTime());
        table.insert(playersTaken, p);
        table.insert(dmgTaken, d);

        -- Keep running totals on group members to shorten calculation times
        -- We'll subtract off the expired entries during OnUpdate                               
        if (dpsTakenTotals[p] == nil) then
        --      print2("dpstotals[p] == nil");
                dpsTakenTotals[p] = d;
        else
        --      print2("dpstotals[p] == " ..dpstotals[p] );
                dpsTakenTotals[p] = dpsTakenTotals[p] + d;
        --      print2("AFTER : dpstotals[p] == " ..dpstotals[p] );
        end
        
        --print2("Total : " ..dpstotals[p]);
end

--      Show the stats collected

function CombatStatsText_OnClick()
   if (CombatStatsDataFrame:IsVisible()) then 
        CombatStatsDataFrame:Hide();
   else
                if (CombatStats_Config.CombatStats_UseMouseOver == 0) then
                        CombatStatsText_ShowFrame();
                end
        end
end

function CombatStatsText_OnEnter()
        if (CombatStats_Config.CombatStats_UseMouseOver == 1) then
                CombatStatsText_ShowFrame();
        end
end

function CombatStatsText_ShowFrame()

        
        if(bFirstTime == 1) then
                
                --
                --      Set all the default values
                --
                
                CombatStatsGeneralNameLabel:SetText(TEXT(CS_FRAME_GEN_ATTACK_NAME));    
                CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_HITS_TEXT);
                CombatStatsGeneralSwingsTextLabel:SetText(CS_FRAME_SWINGS_TEXT);
                CombatStatsGeneralMissesLabel:SetText(CS_FRAME_MISSES_TEXT);
                CombatStatsGeneralDodgesLabel:SetText(CS_FRAME_DODGES_TEXT);
                CombatStatsGeneralParriedLabel:SetText(CS_FRAME_PARRIES_TEXT);
                CombatStatsGeneralBlockedLabel:SetText(CS_FRAME_BLOCKS_TEXT);
                CombatStatsGeneralResistedLabel:SetText(CS_FRAME_RESISTS_TEXT);
                CombatStatsGeneralImmunedLabel:SetText(CS_FRAME_IMMUNE_TEXT);
                CombatStatsGeneralEvadedLabel:SetText(CS_FRAME_EVADES_TEXT );
                CombatStatsGeneralDeflectedLabel:SetText(CS_FRAME_DEFLECTS_TEXT);
                CombatStatsGeneralPercentDmgLabel:SetText(CS_FRAME_PERCENT_OVERALL_TEXT);
                CombatStatsGeneralTimeLastCritLabel:SetText(CS_FRAME_TIME_LASTCRIT_TEXT);
                
                CombatStatsNonCritHitsLabel:SetText(CS_FRAME_TOTAL_TEXT);
                CombatStatsNonCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT);
                CombatStatsNonCritMinMaxLabel:SetText(CS_FRAME_MINMAX_TEXT);
                CombatStatsNonCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT);
                CombatStatsNonCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT);
                
                CombatStatsCritHitsLabel:SetText(CS_FRAME_TOTAL_TEXT);
                CombatStatsCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT);
                CombatStatsCritMinMaxLabel:SetText(CS_FRAME_MINMAX_TEXT);
                CombatStatsCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT);
                CombatStatsCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT);
                
                CombatStatsGeneralNameTextLabel:SetText("N/A");
                
                CombatStatsNonCritHitsStatText:SetText("0");     
                CombatStatsNonCritDamageStatText:SetText("0");           
                CombatStatsNonCritMinMaxStatText:SetText("0 / 0");      
                CombatStatsNonCritAvgStatText:SetText("0.0");   
                CombatStatsNonCritPercentDamageStatText:SetText("0.0 %");       
        
                CombatStatsCritHitsStatText:SetText("0");
                CombatStatsCritDamageStatText:SetText("0");
                CombatStatsCritMinMaxStatText:SetText("0 / 0");
                CombatStatsCritAvgStatText:SetText("0.0");
                CombatStatsCritPercentDamageStatText:SetText("0.0 %");
        
                CombatStatsGeneralTotalHitsHits:SetText("0");    
                CombatStatsGeneralSwingsLabel:SetText("0");
                        
                CombatStatsGeneralMissesTextLabel:SetText("0");  
                CombatStatsGeneralMissesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralDodgesTextLabel:SetText("0");  
                CombatStatsGeneralDodgesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralParriedTextLabel:SetText("0"); 
                CombatStatsGeneralParriedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralBlockedTextLabel:SetText("0"); 
                CombatStatsGeneralBlockedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralResistedTextLabel:SetText("0");        
                CombatStatsGeneralResistedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralImmunedTextLabel:SetText("0"); 
                CombatStatsGeneralImmunedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralEvadedTextLabel:SetText("0");  
                CombatStatsGeneralEvadedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralDeflectedTextLabel:SetText("0");
                CombatStatsGeneralDeflectedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                
                CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
                
                CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE.."N/A");
        
                CombatStatsOverallCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");           
                
                CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."0.0 %");               
                CombatStatsAttackCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
                
                UIDropDownMenu_SetText(CS_DROPDOWN_SELECT_TEXT,CombatStatsAttackDropDown);
                
                bFirstTime = 0;
                
        end
        
        if( UIDropDownMenu_GetText(CombatStatsAttackDropDown) ~= CS_DROPDOWN_SELECT_TEXT) then
                
                CombatStats_UpdateDetails( UIDropDownMenu_GetText(CombatStatsAttackDropDown));
                
        end
        
        CombatStatsDataFrame:Show();
        
end

function CS_ToggleGameMenu(clicked)
        if ( clicked ) then
                if ( OptionsFrame:IsVisible() ) then
                        OptionsFrameCancel:Click();
                end
                if ( GameMenuFrame:IsVisible() ) then
                        PlaySound("igMainMenuQuit");
                        HideUIPanel(GameMenuFrame);
                else
                        CloseMenus();
                        CloseAllWindows()
                        PlaySound("igMainMenuOpen");
                        ShowUIPanel(GameMenuFrame);
                end
                return;
        end
        if ( StaticPopup_EscapePressed() ) then
        elseif ( OptionsFrame:IsVisible() ) then
                OptionsFrameCancel:Click();
        elseif ( GameMenuFrame:IsVisible() ) then
                PlaySound("igMainMenuQuit");
                HideUIPanel(GameMenuFrame);
        elseif ( CloseMenus() ) then
        elseif ( SpellStopCasting() ) then
        elseif ( SpellStopTargeting() ) then
        elseif ( CloseAllWindows() ) then
                CombatStatsDataFrame:Hide();
        elseif ( ClearTarget() ) then
        else
                if ( CombatStatsDataFrame:IsVisible() ) then
                        CombatStatsDataFrame:Hide();
                        return;
                end
                PlaySound("igMainMenuOpen");
                ShowUIPanel(GameMenuFrame);
        end
end

ToggleGameMenu = CS_ToggleGameMenu;

function CombatStats_UpdateDetails(attackName)
        CombatStatsDataFrame.currAttack = attackName;
        if ( strsub(attackName, 0, 6) == "[Heal]" ) then
        
                CS_TT_NONCRIT_HITSPCT_TEXT = CS_TT_NONCRIT_HITSPCT_TEXT_HEAL;
                CS_TT_CRIT_HITSPCT_TEXT = CS_TT_CRIT_HITSPCT_TEXT_HEAL;
                CS_TT_OVERALLDMGPCT_TEXT = CS_TT_OVERALLDMGPCT_TEXT_HEAL;
                CS_TT_CRIT_DMGPCT_TEXT = CS_TT_CRIT_DMGPCT_TEXT_HEAL;
                CS_TT_NONCRIT_DMGPCT_TEXT = CS_TT_NONCRIT_DMGPCT_TEXT_HEAL;

                CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_HITS_TEXT_HEAL);
                CombatStatsGeneralPercentDmgLabel:SetText(CS_FRAME_PERCENT_OVERALL_TEXT_HEAL);
                CombatStatsNonCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT_HEAL);
                CombatStatsNonCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT_HEAL);
                CombatStatsNonCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT_HEAL);
                CombatStatsCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT_HEAL);
                CombatStatsCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT_HEAL);
                CombatStatsCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT_HEAL);

                CombatStatsGeneralSwingsTextLabel:Hide();
        else
                CS_TT_NONCRIT_HITSPCT_TEXT = CS_TT_NONCRIT_HITSPCT_TEXT_NONHEAL;
                CS_TT_CRIT_HITSPCT_TEXT = CS_TT_CRIT_HITSPCT_TEXT_NONHEAL;
                CS_TT_OVERALLDMGPCT_TEXT = CS_TT_OVERALLDMGPCT_TEXT_NONHEAL;
                CS_TT_CRIT_DMGPCT_TEXT = CS_TT_CRIT_DMGPCT_TEXT_NONHEAL;
                CS_TT_NONCRIT_DMGPCT_TEXT = CS_TT_NONCRIT_DMGPCT_TEXT_NONHEAL;

                CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_HITS_TEXT);
                CombatStatsGeneralPercentDmgLabel:SetText(CS_FRAME_PERCENT_OVERALL_TEXT);
                CombatStatsNonCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT);
                CombatStatsNonCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT);
                CombatStatsNonCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT);
                CombatStatsCritDamageLabel:SetText(CS_FRAME_DAMAGE_TEXT);
                CombatStatsCritAvgLabel:SetText(CS_FRAME_AVGDMG_TEXT);
                CombatStatsCritPercentDamageLabel:SetText(CS_FRAME_PERCENTDMG_TEXT);

                CombatStatsGeneralSwingsTextLabel:Show();
        end

        local x,y,info;
        
        --
        --      Draw the text for the hits/swings 
        --
        
        if(attackName ~= "Total") then
                        
        --
        -- Calculate % of hits that are crits
        --              
        
        if( (totalCrits) ~= 0) then             
                CombatStatsOverallCritPctLabel:SetText( format(RED_FONT_COLOR_CODE.."%.2f %%", ( totalCrits / totalHits) * 100.0));                     
        end
        
        CombatStatsGeneralNameTextLabel:SetText(attackName);
        CombatStatsGeneralTotalHitsHits:SetText(specialAttacks[attackName].totalHits);
        if ( strsub(attackName, 0, 6) ~= "[Heal]" ) then
                CombatStatsGeneralSwingsLabel:SetText(specialAttacks[attackName].totalSwings);
                CombatStatsGeneralSwingsLabel:Show();
        else
                CombatStatsGeneralSwingsLabel:Hide();
        end
        
        CombatStatsGeneralMissesTextLabel:SetText(specialAttacks[attackName].totalMisses);
        
        if(specialAttacks[attackName].totalMisses ~= 0) then
                CombatStatsGeneralMissesPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalMisses / (specialAttacks[attackName].totalSwings) * 100)));
        else
                CombatStatsGeneralMissesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralDodgesTextLabel:SetText(specialAttacks[attackName].totalDodged);
        
        if(specialAttacks[attackName].totalDodged ~= 0) then
                CombatStatsGeneralDodgesPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalDodged / (specialAttacks[attackName].totalSwings) * 100)));
        else
                CombatStatsGeneralDodgesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralBlockedTextLabel:SetText(specialAttacks[attackName].totalBlocked);
        
        if(attackName == "Defensive") then
        
                if(specialAttacks[attackName].totalBlocked ~= 0) then
                        CombatStatsGeneralBlockedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalBlocked / (specialAttacks[attackName].totalHits) * 100)));
                else
                        CombatStatsGeneralBlockedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                end
                
        else
        
                if(specialAttacks[attackName].totalBlocked ~= 0) then
                        CombatStatsGeneralBlockedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalBlocked / (specialAttacks[attackName].totalSwings) * 100)));
                else
                        CombatStatsGeneralBlockedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
                end
        
        end
        
        CombatStatsGeneralParriedTextLabel:SetText(specialAttacks[attackName].totalParried);
        
        if(specialAttacks[attackName].totalParried ~= 0) then
                CombatStatsGeneralParriedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalParried / (specialAttacks[attackName].totalSwings) * 100)));
        else
                CombatStatsGeneralParriedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralResistedTextLabel:SetText(specialAttacks[attackName].totalResisted);
        
        if(specialAttacks[attackName].totalResisted ~= 0) then
                CombatStatsGeneralResistedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalResisted / (specialAttacks[attackName].totalSwings) * 100)));
        else
                CombatStatsGeneralResistedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralImmunedTextLabel:SetText(specialAttacks[attackName].totalImmuned);
        
        if(specialAttacks[attackName].totalImmuned ~= 0) then
                CombatStatsGeneralImmunedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalImmuned / (specialAttacks[attackName].totalSwings) * 100)));
        else
                CombatStatsGeneralImmunedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralEvadedTextLabel:SetText(specialAttacks[attackName].totalEvaded);
        
        if(specialAttacks[attackName].totalEvaded ~= 0) then
                CombatStatsGeneralEvadedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalEvaded / (specialAttacks[attackName].totalSwings) * 100)));
        else
                CombatStatsGeneralEvadedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralDeflectedTextLabel:SetText(specialAttacks[attackName].totalDeflected);
        
        if(specialAttacks[attackName].totalDeflected ~= 0) then
                CombatStatsGeneralDeflectedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (specialAttacks[attackName].totalDeflected / (specialAttacks[attackName].totalSwings) * 100)));
        else
                CombatStatsGeneralDeflectedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        --
        --      Percent of total damage
        --
        
        if(attackName ~= "Defensive") then      
                if ( attackName == "[Heal] Total" ) then
                        CombatStatsGeneralPercentDmgPctLabel:SetText("100.0%");
                elseif ( strsub(attackName, 0, 6) == "[Heal]" ) then
                        if ( specialAttacks[attackName].totalHits ~= 0 ) then
                                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) );
                        else
                                CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
                        end
                else
                        
                        if(specialAttacks[attackName].totalHits ~=0) then
                                CombatStatsGeneralPercentDmgPctLabel:SetText( format("%.2f %%",  ((specialAttacks[attackName].totalRegDmg + specialAttacks[attackName].totalCritDmg + specialAttacks[attackName].dotDmg) / totalDamage) * 100) );
                        else
                                CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
                        end
                end
        end
        
        --
        --      Time since last crit
        --
        
        local timeNow;
        timeNow = combatTime;
        
        if(specialAttacks[attackName].lastCrit ~= 0) then
                CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE ..Clock_FormatTime( (timeNow - specialAttacks[attackName].lastCrit)));
        else
                CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE.."N/A");  
        end
        
        --
        --      Attack Crit %
        --
        
        if (specialAttacks[attackName].totalHits ~= 0) and (specialAttacks[attackName].totalCrits ~= 0) then
                CombatStatsAttackCritPctLabel:SetText(format(RED_FONT_COLOR_CODE.."%.1f%%", ( (specialAttacks[attackName].totalCrits) / (specialAttacks[attackName].totalHits)) * 100.0 ));                     
        else
                CombatStatsAttackCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
        end
        
        --
        --      Attack Non Crit %
        --
        
        if (specialAttacks[attackName].totalHits ~= 0) and (specialAttacks[attackName].totalNonCrits ~= 0) then
                CombatStatsAttackNonCritPctLabel:SetText( format(GREEN_FONT_COLOR_CODE.."%.1f%%", ( (specialAttacks[attackName].totalNonCrits) / (specialAttacks[attackName].totalHits)) * 100.0 ));                    
        else
                CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."0.0 %");
        end
        
        --
        --      Non Crit stats
        --
        
        CombatStatsNonCritHitsStatText:SetText(specialAttacks[attackName].totalNonCrits);       
        CombatStatsNonCritDamageStatText:SetText(specialAttacks[attackName].totalRegDmg);       
        CombatStatsNonCritMinMaxStatText:SetText(specialAttacks[attackName].minReg .." / "..specialAttacks[attackName].maxReg);
        
        if( specialAttacks[attackName].totalRegDmg ~= 0) then
                                                                                                
                if( (specialAttacks[attackName].totalHits - specialAttacks[attackName].totalCrits) < 0) then
                        CombatStatsNonCritAvgStatText:SetText(format("%.1f",  specialAttacks[attackName].totalRegDmg / (specialAttacks[attackName].totalCrits - specialAttacks[attackName].totalHits ) ));
                end
                                                
                if(     (specialAttacks[attackName].totalHits - specialAttacks[attackName].totalCrits) == 0 ) then
                        CombatStatsNonCritAvgStatText:SetText(format("%1.f", specialAttacks[attackName].totalRegDmg / (specialAttacks[attackName].totalCrits) ));
                end
                                                
                if(     (specialAttacks[attackName].totalHits - specialAttacks[attackName].totalCrits) > 0 ) then
                        CombatStatsNonCritAvgStatText:SetText(format("%1.f",specialAttacks[attackName].totalRegDmg / (specialAttacks[attackName].totalHits - specialAttacks[attackName].totalCrits) ));
                end
                                                
        else            
                CombatStatsNonCritAvgStatText:SetText("0.0");
        end
        
        if(specialAttacks[attackName].totalNonCrits ~=0) then
                CombatStatsNonCritPercentDamageStatText:SetText( format("%.2f %%", ( specialAttacks[attackName].totalRegDmg   / (specialAttacks[attackName].totalRegDmg + specialAttacks[attackName].totalCritDmg )) * 100.0));
        else
                CombatStatsNonCritPercentDamageStatText:SetText("0.0 %");
        end
        
        --
        --      Crit stats
        --
        
        CombatStatsCritHitsStatText:SetText(specialAttacks[attackName].totalCrits);     
        CombatStatsCritDamageStatText:SetText(specialAttacks[attackName].totalCritDmg); 
        CombatStatsCritMinMaxStatText:SetText(specialAttacks[attackName].minCrit .." / "..specialAttacks[attackName].maxCrit);
        
        if( specialAttacks[attackName].totalCritDmg ~= 0) then
                CombatStatsCritAvgStatText:SetText(format("%1.f", (specialAttacks[attackName].totalCritDmg / specialAttacks[attackName].totalCrits) ));
        else
                CombatStatsCritAvgStatText:SetText("0.0");
        end
        
        if(specialAttacks[attackName].totalCrits ~=0) then
                CombatStatsCritPercentDamageStatText:SetText(format("%.2f %%", (specialAttacks[attackName].totalCritDmg / ( specialAttacks[attackName].totalRegDmg + specialAttacks[attackName].totalCritDmg )) * 100.10 ));
        else
                CombatStatsCritPercentDamageStatText:SetText("0.0 %");
        end     
                                
        --
        --      Show DOT Stats
        --
        
        
                        
        if (specialAttacks[attackName].isDOT ==1) then
                
                CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_TICKS_TEXT);
                CombatStatsGeneralSwingsTextLabel:SetText("");
                CombatStatsGeneralSwingsLabel:SetText("");
                
                CombatStatsGeneralTotalHitsHits:SetText(specialAttacks[attackName].dotTicks);
                CombatStatsNonCritHitsStatText:SetText(specialAttacks[attackName].dotTicks);
                CombatStatsNonCritDamageStatText:SetText(specialAttacks[attackName].dotDmg);
                
                CombatStatsNonCritMinMaxStatText:SetText(specialAttacks[attackName].minReg .." / "..specialAttacks[attackName].maxReg);
                CombatStatsNonCritAvgStatText:SetText(format("%.1f",  specialAttacks[attackName].dotDmg /  specialAttacks[attackName].dotTicks  ));
                CombatStatsNonCritPercentDamageStatText:SetText("100.0 %");
                CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."100.0%");
                
                --
                --      Should never be a 0 tick entry but just in case
                --
--              if(specialAttacks[attackNames[y]].dotTicks ~= 0) then   
--                      text = text.."\n"..format(TEXT(DOT_AVERAGE),(specialAttacks[attackNames[y]].dotDmg / specialAttacks[attackNames[y]].dotTicks));
--              end
        elseif ( specialAttacks[attackName].isDOT ==2) then
                CombatStatsGeneralHitsTextLabel:SetText(CS_FRAME_HOT_TEXT);
                CombatStatsGeneralSwingsTextLabel:SetText("");
                CombatStatsGeneralSwingsLabel:SetText("");
                
                CombatStatsGeneralTotalHitsHits:SetText(specialAttacks[attackName].dotTicks);
                CombatStatsNonCritHitsStatText:SetText(specialAttacks[attackName].dotTicks);
                CombatStatsNonCritDamageStatText:SetText(specialAttacks[attackName].dotDmg);
                
                CombatStatsNonCritMinMaxStatText:SetText(specialAttacks[attackName].minReg .." / "..specialAttacks[attackName].maxReg);
                CombatStatsNonCritAvgStatText:SetText(format("%.1f",  specialAttacks[attackName].dotDmg /  specialAttacks[attackName].dotTicks  ));
                CombatStatsNonCritPercentDamageStatText:SetText("100.0 %");
                CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."100.0%");
        end

        
        else
                
        --
        -- Calculate % of hits that are crits
        --              
        
        if( (totalCrits) ~= 0) then             
                CombatStatsOverallCritPctLabel:SetText( format(RED_FONT_COLOR_CODE.."%.2f %%", ( totalCrits / totalHits) * 100.0));                     
        end
        
        CombatStatsGeneralNameTextLabel:SetText("Total");
        CombatStatsGeneralTotalHitsHits:SetText(totalHits);
        CombatStatsGeneralSwingsLabel:SetText(overallSwings);
        
        CombatStatsGeneralMissesTextLabel:SetText(overallMisses);
        
        if(overallMisses ~= 0) then
                CombatStatsGeneralMissesPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallMisses / (overallSwings) * 100)));
        else
                CombatStatsGeneralMissesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralDodgesTextLabel:SetText(overallDodged);
        
        if(overallDodged ~= 0) then
                CombatStatsGeneralDodgesPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallDodged / (overallSwings) * 100)));
        else
                CombatStatsGeneralDodgesPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralParriedTextLabel:SetText(overallParried);
        
        if(overallParried ~= 0) then
                CombatStatsGeneralParriedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallParried / (overallSwings) * 100)));
        else
                CombatStatsGeneralParriedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralResistedTextLabel:SetText(overallResisted);
        
        if(overallResisted ~= 0) then
                CombatStatsGeneralResistedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallResisted / (overallSwings) * 100)));
        else
                CombatStatsGeneralResistedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralImmunedTextLabel:SetText(overallImmuned);
        
        if(overallImmuned ~= 0) then
                CombatStatsGeneralImmunedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallImmuned / (overallSwings) * 100)));
        else
                CombatStatsGeneralImmunedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralEvadedTextLabel:SetText(overallEvaded);
        
        if(overallEvaded ~= 0) then
                CombatStatsGeneralEvadedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallEvaded / (overallSwings) * 100)));
        else
                CombatStatsGeneralEvadedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        CombatStatsGeneralDeflectedTextLabel:SetText(overallDeflected);
        
        if(overallDeflected ~= 0) then
                CombatStatsGeneralDeflectedPercentLabel:SetText( format(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.. "%.1f%%" .. NORMAL_FONT_COLOR_CODE.." ]", (overallDeflected / (overallSwings) * 100)));
        else
                CombatStatsGeneralDeflectedPercentLabel:SetText(NORMAL_FONT_COLOR_CODE.."[ "..WHITE_FONT_COLOR_CODE.."0.0%"..NORMAL_FONT_COLOR_CODE.." ]");
        end
        
        --
        --      Percent of total damage
        --
        
        if(totalHits ~=0) then
                CombatStatsGeneralPercentDmgPctLabel:SetText( format("%.2f %%",  ((overallRegDmg + overallCritDmg ) / totalDamage) * 100) );
        else
                CombatStatsGeneralPercentDmgPctLabel:SetText("0.0%");
        end
        
        --
        --      Time since last crit
        --
        
        local timeNow;
        timeNow = GetTime();
        
        if(overallLastcrit ~= 0) then
                CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE ..Clock_FormatTime( (timeNow - overallLastcrit)));
        else
                CombatStatsGeneralTimeLastCritTimeLabel:SetText(GREEN_FONT_COLOR_CODE.."N/A");  
        end
        
        --
        --      Attack Crit %
        --
        
        if (totalHits ~= 0) and (overallCrits ~= 0) then
                CombatStatsAttackCritPctLabel:SetText(format(RED_FONT_COLOR_CODE.."%.1f%%", ( (overallCrits) / (totalHits)) * 100.0 ));                 
        else
                CombatStatsAttackCritPctLabel:SetText(RED_FONT_COLOR_CODE.."0.0 %");
        end
        
        --
        --      Attack Non Crit %
        --
        
        if (totalHits ~= 0) and (overallNonCrits ~= 0) then
                CombatStatsAttackNonCritPctLabel:SetText( format(GREEN_FONT_COLOR_CODE.."%.1f%%", ( (overallNonCrits) / (totalHits)) * 100.0 ));                        
        else
                CombatStatsAttackNonCritPctLabel:SetText(GREEN_FONT_COLOR_CODE.."0.0 %");
        end
        
        --
        --      Non Crit stats
        --
        
        CombatStatsNonCritHitsStatText:SetText(overallNonCrits);        
        CombatStatsNonCritDamageStatText:SetText(overallRegDmg);        
        CombatStatsNonCritMinMaxStatText:SetText(overallminReg .." / "..overallmaxReg);
        
        if( overallRegDmg ~= 0) then
                                                                                                
                if( (totalHits - overallCrits) < 0) then
                        CombatStatsNonCritAvgStatText:SetText(format("%.1f",  overallRegDmg / (overallCrits - totalHits ) ));
                end
                                                
                if(     (totalHits - overallCrits) == 0 ) then
                        CombatStatsNonCritAvgStatText:SetText(format("%1.f", overallRegDmg / (overallCrits) ));
                end
                                                
                if(     (totalHits - overallCrits) > 0 ) then
                        CombatStatsNonCritAvgStatText:SetText(format("%1.f", overallRegDmg / (totalHits - overallCrits) ));
                end
                                                
        else            
                CombatStatsNonCritAvgStatText:SetText("0.0");
        end
        
        if(overallNonCrits ~=0) then
                CombatStatsNonCritPercentDamageStatText:SetText( format("%.2f %%", ( overallRegDmg  / (overallRegDmg + overallCritDmg )) * 100.0));
        else
                CombatStatsNonCritPercentDamageStatText:SetText("0.0 %");
        end
        
        --
        --      Crit stats
        --
        
        CombatStatsCritHitsStatText:SetText(overallCrits);      
        CombatStatsCritDamageStatText:SetText(overallCritDmg);  
        CombatStatsCritMinMaxStatText:SetText(overallminCrit .." / "..overallmaxCrit);
        
        if( overallCritDmg ~= 0) then
                CombatStatsCritAvgStatText:SetText(format("%1.f", (overallCritDmg / overallCrits) ));
        else
                CombatStatsCritAvgStatText:SetText("0.0");
        end
        
        if(overallCrits ~=0) then
                CombatStatsCritPercentDamageStatText:SetText(format("%.2f %%", (overallCritDmg / ( overallRegDmg + overallCritDmg )) * 100.10 ));
        else
                CombatStatsCritPercentDamageStatText:SetText("0.0 %");
        end     
        
        end
        
end                                     


--
--  Time functions
--  from Clock.lua
--

local function Clock_FormatPart(fmt, val)
        local part;

        part = format(TEXT(fmt), val);
        if( val ~= 1 ) then
                part = part.."s";
        end

        return part;
end

function Clock_FormatTime(time)
        local d, h, m, s;
        local text = "";
        local skip = 1;

        if ( time == 0 ) then return Clock_FormatPart(CLOCK_TIME_SECOND, 0); end

        d, h, m, s = ChatFrame_TimeBreakDown(time);
        if( d > 0 ) then
                text = text..Clock_FormatPart(CLOCK_TIME_DAY, d)..", ";
                skip = 0;
        end
        if( (skip == 0) or (h > 0) ) then
                text = text..Clock_FormatPart(CLOCK_TIME_HOUR, h)..", ";
                skip = 0;
        end
        if( (skip == 0) or (m > 0) ) then
                text = text..Clock_FormatPart(CLOCK_TIME_MINUTE, m)..", ";
                skip = 0;
        end
        if( (skip == 0) or (s > 0) ) then
                text = text..Clock_FormatPart(CLOCK_TIME_SECOND, s);
        end

        return text;
end

function CombatStats_TargetFrame_OnShow()
        if (CombatStats_Old_TargetFrame_OnShow) then
                CombatStats_Old_TargetFrame_OnShow();
        end
        CombatStats_UpdateVisibility(1);
end

function CombatStats_TargetFrame_OnHide()
        if (CombatStats_Old_TargetFrame_OnHide) then
                CombatStats_Old_TargetFrame_OnHide();
        end
        CombatStats_UpdateVisibility(0);
end