vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
--[[
        Stuff to track spell casting
        
        Main usage in SW Stats: Track mana efficiency of spells
        Might add more here
        
        Basic idea from:
        http://www.wowwiki.com/HOWTO:_Detecting_Instant_Cast_Spells
        
        approach for cancel, stop is different
        
        for ae we accept the spell at SPELLCAST_CHANNEL_START
        Stop messages for instant casts are never made pending, stop + instant = ok
        
        The idea of the "pending cast" is used because a fail message can come after a stop message for "normal" spells.
        
--]]

-- holds mana / spell info for cast by name
SW_CastByNameLookup = {};
-- holds mana / spell info for cast by name without rank
SW_CastByNameLookupMax = {};

--spells that are instant
SW_InstantLookup = {};

-- holds info until know if a spell failed
SW_PendingCast = {};
-- holds info of the spell to cast
SW_SelectedSpell = {};

local SW_ManaRegEx = string.gsub(MANA_COST, "%%d","(%%d+)");

function SW_GetManaCost(str)
        if str == nil then return nil; end
        local _,_, spellCost = string.find(str, SW_ManaRegEx);
        if spellCost == nil then return nil; end
        return tonumber(spellCost);
end

function SW_CalcManaUsage()
        local who = SW_S_Details[SW_SELF_STRING];
        if who == nil then return; end
        
        local perSpell = SW_S_SpellInfo[SW_SELF_STRING];
        if perSpell == nil then return; end
        
        local manaUsage = {0, 0, 0}; -- dmg, heal, total mana
        local manaUsed = 0;
        
        for k,v in pairs(perSpell) do
                if k ~= SW_DECURSEDUMMY then
                        manaUsage[3] = manaUsage[3] + v[2];
                        
                        if who[k] ~= nil then
                                manaUsed = v[2];
                                if manaUsed > 0 then
                                        
                                        if who[k][1] > 0 then
                                                manaUsage[1] = manaUsage[1] + manaUsed;                                         
                                        end
                                        if who[k][2] > 0 then
                                                manaUsage[2] = manaUsage[2] + manaUsed;
                                        end
                                end
                        end     
                end
        end
        
        SW_S_ManaUsage[SW_SELF_STRING] = {manaUsage[1],manaUsage[2],manaUsage[3]}; -- dmg, heal, total.
        
        
end
function SW_AcceptPendingCast()
        --SW_printStr("SW_AcceptPendingCast");
        local spN = SW_PendingCast[1];
        if spN == nil then
                SW_PendingCast = {};
                return;
        end
        --SW_printStr(spN);
        --SW_printStr("-SW_AcceptPendingCast-"..spN);
        local updateMana = (SW_PendingCast[2] > 0);
        
        if SW_S_SpellInfo[SW_SELF_STRING] == nil then
                SW_S_SpellInfo[SW_SELF_STRING] = {};
        end
        if SW_S_SpellInfo[SW_SELF_STRING][spN] == nil then
                SW_S_SpellInfo[SW_SELF_STRING][spN] = {0,0};
        end
        spN = SW_S_SpellInfo[SW_SELF_STRING][spN];
        spN[1] = spN[1] + 1;
        spN[2] = spN[2] + SW_PendingCast[2];
        
        SW_PendingCast = {};
        
        -- only update this if mana was really used
        if updateMana then
                SW_CalcManaUsage();
        end
end
-- used in special cases see SPELLCAST_STOP in core.lua
function SW_AcceptSelectedCast()
        --SW_printStr("SW_AcceptSelectedCast");
        local spN = SW_SelectedSpell[1];
        if spN == nil then
                SW_SelectedSpell = {};
                return;
        end
        --SW_printStr(spN);
        --SW_printStr("-SW_AcceptSelectedCast-"..spN);
        local updateMana = (SW_SelectedSpell[2] > 0);
        
        if SW_S_SpellInfo[SW_SELF_STRING] == nil then
                SW_S_SpellInfo[SW_SELF_STRING] = {};
        end
        if SW_S_SpellInfo[SW_SELF_STRING][spN] == nil then
                SW_S_SpellInfo[SW_SELF_STRING][spN] = {0,0};
        end
        spN = SW_S_SpellInfo[SW_SELF_STRING][spN];
        spN[1] = spN[1] + 1;
        spN[2] = spN[2] + SW_SelectedSpell[2];
        
        SW_SelectedSpell = {};
        
        -- only update this if mana was really used
        if updateMana then
                SW_CalcManaUsage();
        end     
end
function SW_UpdateCastByNameLookup()
        local i = 1
        local spellCost;
        --SW_printStr("SW_CastByNameLookup rebuilt");
        SW_CastByNameLookup = {};
        SW_CastByNameLookupMax = {};
        SW_InstantLookup = {};
        SW_SpellHookTT:SetOwner(UIParent, "ANCHOR_NONE");

        while true do
                local spellName, spellRank = GetSpellName(i, BOOKTYPE_SPELL)
                if not spellName then
                        do break end
                end
                SW_SpellHookTT:SetSpell(i, BOOKTYPE_SPELL);
                if ( spellRank and (strlen(spellRank) > 0) ) then
                        
                        spellCost = SW_GetManaCost(SW_SpellHookTTTextLeft2:GetText());
                        if spellCost == nil then
                                SW_CastByNameLookup[ spellName .. '(' .. spellRank .. ')' ] = {spellName, spellRank, 0};
                        else
                                SW_CastByNameLookup[ spellName .. '(' .. spellRank .. ')' ] = {spellName, spellRank, spellCost};
                        end
                        
                else
                        spellCost = SW_GetManaCost(SW_SpellHookTTTextLeft2:GetText());
                        if spellCost == nil then
                                SW_CastByNameLookup[ spellName ] = {spellName, nil, 0};
                        else
                                SW_CastByNameLookup[ spellName ] = {spellName, nil, spellCost};
                        end
                end
                if SW_CastByNameLookupMax[spellName] == nil or spellCost > SW_CastByNameLookupMax[spellName] then
                        SW_CastByNameLookupMax[spellName] = spellCost;
                end
                if (SPELL_CAST_TIME_INSTANT == SW_SpellHookTTTextLeft3:GetText()) then
                        SW_InstantLookup[ spellName ] = true;
                end
                
                i = i + 1
        end
end


SWHook_oldCastSpell = CastSpell;
function SWHook_newCastSpell(spellId, spellbookTabNum)
        --SW_printStr("CastSpell");
        -- if we are casting something already, do normal stuff
        -- don't need to check .channeling a new cast abborts channeling
        if getglobal("CastingBarFrame").casting then
                SWHook_oldCastSpell(spellId, spellbookTabNum);
                return;
        end
        SW_SpellHookTT:SetOwner(UIParent, "ANCHOR_NONE");
        -- Load the tooltip with the spell information
        SW_SpellHookTT:SetSpell(spellId, spellbookTabNum);
        local spellName = SW_SpellHookTTTextLeft1:GetText();
        if spellName == nil then
                SWHook_oldCastSpell(spellId, spellbookTabNum);
                return;
        end
        
        local spellCost = SW_GetManaCost(SW_SpellHookTTTextLeft2:GetText());
        local instant = SW_InstantLookup[spellName];
        
        if spellCost == nil then
                SW_SelectedSpell = {spellName, 0, instant};
        else
                SW_SelectedSpell = {spellName, spellCost, instant};
        end
        SWHook_oldCastSpell(spellId, spellbookTabNum);
end
CastSpell = SWHook_newCastSpell;

--1.3.2 changed this to be wow 1.10 ready (onSelf will be added)
SWHook_oldCastSpellByName = CastSpellByName;
function SWHook_newCastSpellByName(spellName, onSelf)
        if getglobal("CastingBarFrame").casting then
                SWHook_oldCastSpellByName(spellName, onSelf)
                return;
        end
        
        local spell, spellCost;
        
        if SW_CastByNameLookup[spellName] ~= nil then
                spell = SW_CastByNameLookup[spellName][1];
                spellCost = SW_CastByNameLookup[spellName][3];
        elseif SW_CastByNameLookupMax[spellName] ~= nil then
                spell = spellName;
                spellCost = SW_CastByNameLookupMax[spellName];
        end
        local instant = SW_InstantLookup[spellName];
        -- can happen if we are using a macro of a spell we dont have
        if spell ~= nil and spellCost~= nil and spellCost > 0 then
                SW_SelectedSpell = {spell, spellCost, instant};
        end
        
        -- Call the original function
        SWHook_oldCastSpellByName(spellName, onSelf)

end
CastSpellByName = SWHook_newCastSpellByName;


SWHook_oldUseAction = UseAction

function SWHook_newUseAction(a1, a2, a3)
        --SW_printStr("Action");
        if getglobal("CastingBarFrame").casting then
                SWHook_oldUseAction(a1, a2, a3);
                return;
        end
        
        -- Call the original function
        SWHook_oldUseAction(a1, a2, a3);
        
        -- Test to see if this is a macro
        if GetActionText(a1) then 
                return ;
        end
        SW_SpellHookTT:SetOwner(UIParent, "ANCHOR_NONE");
        
        SW_SpellHookTT:SetAction(a1)
        
        -- need to lookup the info this way because the "enhanced tooltip" could be turned off.
        -- name and rank are always displayed. 
        local spellNRank = "";
        local spellCost;
        local spell = SW_SpellHookTTTextLeft1:GetText();
        if spell == nil then 
                return;
        end
        local instant = SW_InstantLookup[spell];
        local spellRank = SW_SpellHookTTTextRight1:GetText();
        if ( spellRank and (strlen(spellRank) > 0) ) then
                spellNRank = spell.."("..spellRank..")";
        else
                spellNRank = spell;
        end
        if SW_CastByNameLookup[spellNRank] ~= nil then
                spellCost = SW_CastByNameLookup[spellNRank][3];
        end
        
        if spellCost == nil then
                --SW_printStr(spellName);
                SW_SelectedSpell = {spell, 0, instant};
        else
                SW_SelectedSpell = {spell, spellCost, instant};
        end
end
UseAction = SWHook_newUseAction

--[[ usless same event order
SWHook_oldCastingBarFrame_OnEvent = CastingBarFrame_OnEvent
function SWHook_newCastingBarFrame_OnEvent()
        if ( event == "SPELLCAST_START" ) then
                SW_printStr("CBE_SPELLCAST_START");
        elseif ( event == "SPELLCAST_STOP" ) then
                SW_printStr("CBE_SPELLCAST_STOP");
        elseif ( event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED" ) then
                SW_printStr("CBE_SPELLCAST_FAILED");
        elseif ( event == "SPELLCAST_DELAYED" ) then
                SW_printStr("CBE_SPELLCAST_DELAYED");
        elseif ( event == "SPELLCAST_CHANNEL_START" ) then
                SW_printStr("CBE_SPELLCAST_CHANNEL_START");
        elseif ( event == "SPELLCAST_CHANNEL_UPDATE" ) then
                SW_printStr("CBE_SPELLCAST_CHANNEL_UPDATE");
        end
        SWHook_oldCastingBarFrame_OnEvent();
end
CastingBarFrame_OnEvent = SWHook_newCastingBarFrame_OnEvent;
--]]