--[[ 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; --]]